From 1c151c12a186a1c28b87f1c9b35b063a01db7339 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 21:00:05 +0200 Subject: [PATCH 01/22] Update docu --- docs/make.jl | 32 ++++++ {doc => docs/src}/airdensity.png | Bin docs/src/index.md | 160 +++++++++++++++++++++++++++++ {doc => docs/src}/wind_profile.png | Bin scripts/build_docu.jl | 24 +++++ 5 files changed, 216 insertions(+) create mode 100644 docs/make.jl rename {doc => docs/src}/airdensity.png (100%) create mode 100644 docs/src/index.md rename {doc => docs/src}/wind_profile.png (100%) create mode 100644 scripts/build_docu.jl diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 0000000..bfef480 --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,32 @@ +using KiteUtils +using Pkg +if ("TestEnv" ∈ keys(Pkg.project().dependencies)) + if ! ("Documents" ∈ keys(Pkg.project().dependencies)) + using TestEnv; TestEnv.activate() + end +end +using Documenter + +DocMeta.setdocmeta!(KiteUtils, :DocTestSetup, :(using KiteUtils); recursive=true) + +makedocs(; + modules=[AtmosphericModels], + authors="Uwe Fechner and contributors", + repo="https://github.com/OpenSourceAWE/KiteUtils.jl/blob/{commit}{path}#{line}", + sitename="AtmosphericModels.jl", + checkdocs=:none, + format=Documenter.HTML(; + repolink = "https://github.com/OpenSourceAWE/AtmosphericModels.jl", + prettyurls=get(ENV, "CI", "false") == "true", + canonical="https://OpenSourceAWE.github.io/AtmosphericModels.jl", + assets=String[], + ), + pages=[ + "Home" => "index.md", + ], +) + +deploydocs(; + repo="github.com/OpenSourceAWE/AtmosphericModels.jl", + devbranch="main", +) diff --git a/doc/airdensity.png b/docs/src/airdensity.png similarity index 100% rename from doc/airdensity.png rename to docs/src/airdensity.png diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..8938bf3 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,160 @@ +```@meta +CurrentModule = KiteUtils +``` +# AtmosphericModels +This package provides functions for modelling the influence of the atmosphere on wind energy systems. It models the air density, the vertical wind profile and the wind turbulence. Further functions to import measured data are planned. + +## Installation +Install [Julia 1.10](http://www.julialang.org) or later, if you haven't already. You can add AtmosphericModels from Julia's package manager, by typing +```julia +using Pkg +pkg"add AtmosphericModels" +``` +at the Julia prompt. + +## Exported types +```julia +AtmosphericModel +@enum ProfileLaw EXP=1 LOG=2 EXPLOG=3 FAST_EXP=4 FAST_LOG=5 FAST_EXPLOG=6 +``` + +## Exported functions +```julia +clear(s::AM) +calc_rho(s::AM, height) +calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) +``` +## Wind profile + +

+ +The EXPLOG profile law is the fitted linear combination of the exponential and the log law. + +## Usage +```julia +using AtmosphericModels +am = AtmosphericModel() + +const profile_law = Int(EXPLOG) +height = 100.0 +wf = calc_wind_factor(am, height, profile_law) +``` +The result is the factor with which the ground wind speed needs to be multiplied +to get the wind speed at the given height. + +## Using the turbulent wind field +You can get a wind vector as function of x,y,z and time using the following code: +``` +using AtmosphericModels, KiteUtils + +set_data_path("data") +set = load_settings("system.yaml") +am::AtmosphericModel = AtmosphericModel(set) + +@info "Ground wind speed: $(am.set.v_wind) m/s" + +wf::WindField = WindField(am, am.set.v_wind) +x, y, z = 20.0, 0.0, 200.0 +t = 0.0 +vx, vy, vz = get_wind(wf, am, x, y, z, t) +@time get_wind(am, x, y, z, t) +@info "Wind at x=$(x), y=$(y), z=$(z), t=$(t): v_x=$(vx), v_y=$(vy), v_z=$(vz)" +@info "Wind speed: $(sqrt(vx^2 + vy^2 + vz^2)) m/s" +``` +It is suggested to check out the code using git before executing this example, +because it requires that a data directory with the correct files `system.yaml` +and `settings.yaml` exists. See below how to do that. + +## Plot a wind profile +```julia +using AtmosphericModels, KiteUtils, ControlPlots +am = AtmosphericModel(se()) + +heights = 6:1000 +wf = [calc_wind_factor(am, height, Int(EXPLOG)) for height in heights] + +plot(heights, wf, xlabel="height [m]", ylabel="wind factor") +``` + +```julia +using AtmosphericModels, ControlPlots, KiteUtils +am = AtmosphericModel(se()) +AtmosphericModels.se().alpha = 0.234 # set the exponent of the power law + +heights = 6:200 +wf = [calc_wind_factor(am, height, Int(EXP)) for height in heights] + +plot(heights, wf, xlabel="height [m]", ylabel="wind factor") +``` + +## Benchmark +```julia +using AtmosphericModels, BenchmarkTools, KiteUtils + +am = AtmosphericModel(se()) +@benchmark calc_wind_factor(am, height, Int(EXPLOG)) setup=(height=Float64((6.0+rand()*500.0))) +``` +|Profile law|time [ns]| +| --- |:---:| +|EXP |12 | +|LOG |16 | +|EXPLOG |33 | +|FAST_EXP|6.6 | +|FAST_LOG|6.6 | +|FAST_EXPLOG|6.6| + +The FAST versions are an approximations with an error of less than $1.5 \cdot 10^{-5}$ and are correct only for the default values of h_ref, z0 and alpha. + +## Air density +```julia +using AtmosphericModels, BenchmarkTools, KiteUtils +am = AtmosphericModel(se()) +@benchmark calc_rho(am, height) setup=(height=Float64((6.0+rand()*500.0))) +``` +This gives 4.85 ns as result. Plot the air density: +```julia +heights = 6:1000 +rhos = [calc_rho(am, height) for height in heights] +plot(heights, rhos, legend=false, xlabel="height [m]", ylabel="air density [kg/m³]") +``` +

+ +## Running the tests +Launch Julia using this project and run the tests: +```julia +julia --project +using Pkg +Pkg.test("AtmosphericModels") +``` + +## Running the examples +If you check out the project using git, you can more easily run the examples: +``` +git clone https://github.com/OpenSourceAWE/AtmosphericModels.jl +cd AtmosphericModels.jl +``` +Launch Julia using this project and run the example menu: +```julia +julia --project +include("examples/menu.jl") +``` +The first time will take some time, because the graphic libraries will get installed, the second time it is fast. + +## Further reading +These models are described in detail in [Dynamic Model of a Pumping Kite Power System](http://arxiv.org/abs/1406.6218). + +## Licence +This project is licensed under the MIT License. Please see the below WAIVER in association with the license. + +## WAIVER +Technische Universiteit Delft hereby disclaims all copyright interest in the package “AtmosphericModels.jl” (models for airborne wind energy systems) written by the Author(s). + +Prof.dr. H.G.C. (Henri) Werij, Dean of Aerospace Engineering + +## See also +- [Research Fechner](https://research.tudelft.nl/en/publications/?search=Uwe+Fechner&pageSize=50&ordering=rating&descending=true) +- The application [KiteViewer](https://github.com/ufechner7/KiteViewer) +- the package [KiteUtils](https://github.com/ufechner7/KiteUtils.jl) +- the packages [KiteModels](https://github.com/ufechner7/KiteModels.jl) and [WinchModels](https://github.com/aenarete/WinchModels.jl) and [KitePodModels](https://github.com/aenarete/KitePodModels.jl) +- the packages [KiteControllers](https://github.com/aenarete/KiteControllers.jl) and [KiteViewers](https://github.com/aenarete/KiteViewers.jl) + diff --git a/doc/wind_profile.png b/docs/src/wind_profile.png similarity index 100% rename from doc/wind_profile.png rename to docs/src/wind_profile.png diff --git a/scripts/build_docu.jl b/scripts/build_docu.jl new file mode 100644 index 0000000..f519c1a --- /dev/null +++ b/scripts/build_docu.jl @@ -0,0 +1,24 @@ +# build and display the html documentation locally +# you must have installed the package LiveServer in your global environment + +using Pkg + +function globaldependencies() + projectpath = Pkg.project().path + basepath, _ = splitdir(projectpath) + Pkg.activate() + globaldependencies = keys(Pkg.project().dependencies) + Pkg.activate(basepath) + globaldependencies +end + +if !("LiveServer" in globaldependencies()) + println("Installing LiveServer globally!") + run(`julia -e 'using Pkg; Pkg.add("LiveServer")'`) +end + +# if !("Documenter" ∈ keys(Pkg.project().dependencies)) +# using TestEnv +# TestEnv.activate() +# end +using LiveServer; servedocs(launch_browser=true) From a0afc4bc3a4228b1dea6ff3a22936512ca7960c0 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 21:06:54 +0200 Subject: [PATCH 02/22] Some progress --- .gitignore | 1 + Project.toml | 4 +++- docs/make.jl | 4 ++-- scripts/build_docu.jl | 8 ++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 7990bbb..59a51f7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ data/windfield_4050_500_1.0_8.2.npz examples/Manifest.toml examples/Manifest-v1.10.toml examples/Manifest-v1.11.toml +docs/build diff --git a/Project.toml b/Project.toml index 41b8c6a..adfe8b7 100644 --- a/Project.toml +++ b/Project.toml @@ -16,6 +16,7 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [compat] ControlPlots = "0.2.7" +Documenter = "1.13.0" FFTW = "1.9.0" HypergeometricFunctions = "0.3" KiteUtils = "0.6, 0.7, 0.8, 0.9, 0.10" @@ -30,8 +31,9 @@ julia = "1.10, 1.11" [extras] BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" ControlPlots = "23c2ee80-7a9e-4350-b264-8e670f12517c" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Remez = "2e7db186-766a-50e7-8928-5c30181fb135" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test", "BenchmarkTools", "Remez", "ControlPlots"] +test = ["Test", "BenchmarkTools", "Remez", "ControlPlots", "Documenter"] diff --git a/docs/make.jl b/docs/make.jl index bfef480..06175d4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,4 +1,4 @@ -using KiteUtils +using KiteUtils, AtmosphericModels using Pkg if ("TestEnv" ∈ keys(Pkg.project().dependencies)) if ! ("Documents" ∈ keys(Pkg.project().dependencies)) @@ -7,7 +7,7 @@ if ("TestEnv" ∈ keys(Pkg.project().dependencies)) end using Documenter -DocMeta.setdocmeta!(KiteUtils, :DocTestSetup, :(using KiteUtils); recursive=true) +DocMeta.setdocmeta!(AtmosphericModels, :DocTestSetup, :(using AtmosphericModels); recursive=true) makedocs(; modules=[AtmosphericModels], diff --git a/scripts/build_docu.jl b/scripts/build_docu.jl index f519c1a..f88f437 100644 --- a/scripts/build_docu.jl +++ b/scripts/build_docu.jl @@ -17,8 +17,8 @@ if !("LiveServer" in globaldependencies()) run(`julia -e 'using Pkg; Pkg.add("LiveServer")'`) end -# if !("Documenter" ∈ keys(Pkg.project().dependencies)) -# using TestEnv -# TestEnv.activate() -# end +if !("Documenter" ∈ keys(Pkg.project().dependencies)) + using TestEnv + TestEnv.activate() +end using LiveServer; servedocs(launch_browser=true) From 94fa417820624c60c54d8f5bea596445a331d4fa Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 21:26:21 +0200 Subject: [PATCH 03/22] Some updates --- docs/src/index.md | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 8938bf3..12f35be 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -24,13 +24,9 @@ clear(s::AM) calc_rho(s::AM, height) calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) ``` -## Wind profile - -

- -The EXPLOG profile law is the fitted linear combination of the exponential and the log law. ## Usage +### Calculate the height dependant wind speed ```julia using AtmosphericModels am = AtmosphericModel() @@ -42,9 +38,13 @@ wf = calc_wind_factor(am, height, profile_law) The result is the factor with which the ground wind speed needs to be multiplied to get the wind speed at the given height. -## Using the turbulent wind field +![Wind Profile](wind_profile.png) + +The `EXPLOG` profile law is the fitted linear combination of the exponential and the log law. + +### Using the turbulent wind field You can get a wind vector as function of x,y,z and time using the following code: -``` +```julia using AtmosphericModels, KiteUtils set_data_path("data") @@ -65,7 +65,7 @@ It is suggested to check out the code using git before executing this example, because it requires that a data directory with the correct files `system.yaml` and `settings.yaml` exists. See below how to do that. -## Plot a wind profile +### Plot a wind profile ```julia using AtmosphericModels, KiteUtils, ControlPlots am = AtmosphericModel(se()) @@ -87,25 +87,7 @@ wf = [calc_wind_factor(am, height, Int(EXP)) for height in heights] plot(heights, wf, xlabel="height [m]", ylabel="wind factor") ``` -## Benchmark -```julia -using AtmosphericModels, BenchmarkTools, KiteUtils - -am = AtmosphericModel(se()) -@benchmark calc_wind_factor(am, height, Int(EXPLOG)) setup=(height=Float64((6.0+rand()*500.0))) -``` -|Profile law|time [ns]| -| --- |:---:| -|EXP |12 | -|LOG |16 | -|EXPLOG |33 | -|FAST_EXP|6.6 | -|FAST_LOG|6.6 | -|FAST_EXPLOG|6.6| - -The FAST versions are an approximations with an error of less than $1.5 \cdot 10^{-5}$ and are correct only for the default values of h_ref, z0 and alpha. - -## Air density +### Air density ```julia using AtmosphericModels, BenchmarkTools, KiteUtils am = AtmosphericModel(se()) @@ -117,7 +99,7 @@ heights = 6:1000 rhos = [calc_rho(am, height) for height in heights] plot(heights, rhos, legend=false, xlabel="height [m]", ylabel="air density [kg/m³]") ``` -

+![Airdensity](airdensity.png) ## Running the tests Launch Julia using this project and run the tests: From e7ab31bfa37dd9c4a878a623c7f60e096ca1c969 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 21:35:03 +0200 Subject: [PATCH 04/22] Improve docu --- docs/make.jl | 1 + docs/src/api.md | 22 ++++++++++++++++++++++ docs/src/index.md | 45 ++++++++++++++++----------------------------- 3 files changed, 39 insertions(+), 29 deletions(-) create mode 100644 docs/src/api.md diff --git a/docs/make.jl b/docs/make.jl index 06175d4..99bde98 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -23,6 +23,7 @@ makedocs(; ), pages=[ "Home" => "index.md", + "API" => "api.md", ], ) diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..75b32e7 --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,22 @@ +```@meta +CurrentModule = AtmosphericModels +``` + +## Introduction + +## Types + +### Exported types +```julia +AtmosphericModel +@enum ProfileLaw EXP=1 LOG=2 EXPLOG=3 FAST_EXP=4 FAST_LOG=5 FAST_EXPLOG=6 +``` + +## Functions + +### Exported functions +```julia +clear(s::AM) +calc_rho(s::AM, height) +calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) +``` \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index 12f35be..832c1d4 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,5 @@ ```@meta -CurrentModule = KiteUtils +CurrentModule = AtmosphericModels ``` # AtmosphericModels This package provides functions for modelling the influence of the atmosphere on wind energy systems. It models the air density, the vertical wind profile and the wind turbulence. Further functions to import measured data are planned. @@ -12,18 +12,26 @@ pkg"add AtmosphericModels" ``` at the Julia prompt. -## Exported types +### Running the tests +Launch Julia using this project and run the tests: ```julia -AtmosphericModel -@enum ProfileLaw EXP=1 LOG=2 EXPLOG=3 FAST_EXP=4 FAST_LOG=5 FAST_EXPLOG=6 +julia --project +using Pkg +Pkg.test("AtmosphericModels") ``` -## Exported functions +### Running the examples +If you check out the project using git, you can more easily run the examples: +``` +git clone https://github.com/OpenSourceAWE/AtmosphericModels.jl +cd AtmosphericModels.jl +``` +Launch Julia using this project and run the example menu: ```julia -clear(s::AM) -calc_rho(s::AM, height) -calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) +julia --project +include("examples/menu.jl") ``` +The first time will take some time, because the graphic libraries will get installed, the second time it is fast. ## Usage ### Calculate the height dependant wind speed @@ -101,27 +109,6 @@ plot(heights, rhos, legend=false, xlabel="height [m]", ylabel="air density [kg/m ``` ![Airdensity](airdensity.png) -## Running the tests -Launch Julia using this project and run the tests: -```julia -julia --project -using Pkg -Pkg.test("AtmosphericModels") -``` - -## Running the examples -If you check out the project using git, you can more easily run the examples: -``` -git clone https://github.com/OpenSourceAWE/AtmosphericModels.jl -cd AtmosphericModels.jl -``` -Launch Julia using this project and run the example menu: -```julia -julia --project -include("examples/menu.jl") -``` -The first time will take some time, because the graphic libraries will get installed, the second time it is fast. - ## Further reading These models are described in detail in [Dynamic Model of a Pumping Kite Power System](http://arxiv.org/abs/1406.6218). From 2d1ff9e312dbb45cad579bcffc7c87e18b3f56d4 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:03:22 +0200 Subject: [PATCH 05/22] Improve docstrings --- docs/src/api.md | 6 +++++- src/AtmosphericModels.jl | 20 +++++++++++++++++++- src/windfield.jl | 5 ++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/src/api.md b/docs/src/api.md index 75b32e7..e23cc66 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -17,6 +17,10 @@ AtmosphericModel ### Exported functions ```julia clear(s::AM) -calc_rho(s::AM, height) calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) +``` + +```@docs +calc_rho +get_wind ``` \ No newline at end of file diff --git a/src/AtmosphericModels.jl b/src/AtmosphericModels.jl index f3ac2e1..60b3bf3 100644 --- a/src/AtmosphericModels.jl +++ b/src/AtmosphericModels.jl @@ -52,6 +52,7 @@ end const AM = AtmosphericModel + function clear(s::AM) s.rho_zero_temp = (15.0 - ABS_ZERO) / (s.set.temp_ref - ABS_ZERO) * s.set.rho_0 end @@ -63,7 +64,24 @@ end y end -# Calculate the air densisity as function of height +""" + calc_rho(s::AM, height) + +Calculates the air density at a given height above ground level. + +# Arguments +- `s::AM`: An instance of the `AM` (Atmospheric Model) struct containing atmospheric parameters. +- `height`: The height above ground level (in meters) at which to calculate the air density. + +# Returns +- The air density at the specified height (in kg/m³). + +# Notes +- The calculation assumes an exponential decrease of air density with altitude. +- `s.rho_zero_temp` is the reference air density at ground level. +- `s.set.height_gnd` is the ground height offset. +- The scale height used is 8550.0 meters. +""" calc_rho(s::AM, height) = s.rho_zero_temp * fastexp(-(height+s.set.height_gnd) / 8550.0) """ diff --git a/src/windfield.jl b/src/windfield.jl index 3961e46..906cdd0 100644 --- a/src/windfield.jl +++ b/src/windfield.jl @@ -271,13 +271,12 @@ function create_windfield(x, y, z; sigma1=nothing, gamma=3.9, ae=0.1, length_sca end """ - get_wind(wf::WindField, am::AtmosphericModel, x, y, z, t; interpolate=false) + get_wind(am::AtmosphericModel, x, y, z, t; interpolate=false) Returns the wind vector at the specified position (`x`, `y`, `z`) and time `t` using the given -`WindField` (`wf`) and `AtmosphericModel` (`am`). +`AtmosphericModel` (`am`). # Arguments -- `wf::WindField`: The wind field object containing wind data. - `am::AtmosphericModel`: The atmospheric model providing environmental parameters. - `x`, `y`, `z`: Coordinates specifying the location where the wind is to be evaluated. [m] - `t`: Time at which the wind is to be evaluated. [s] From 7c6fdb1107e4524d6d0d4c83e8389f534568bdd6 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:11:18 +0200 Subject: [PATCH 06/22] Document clear --- docs/src/api.md | 2 +- src/AtmosphericModels.jl | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/src/api.md b/docs/src/api.md index e23cc66..192cfc5 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -16,11 +16,11 @@ AtmosphericModel ### Exported functions ```julia -clear(s::AM) calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) ``` ```@docs +clear calc_rho get_wind ``` \ No newline at end of file diff --git a/src/AtmosphericModels.jl b/src/AtmosphericModels.jl index 60b3bf3..748ffde 100644 --- a/src/AtmosphericModels.jl +++ b/src/AtmosphericModels.jl @@ -52,9 +52,20 @@ end const AM = AtmosphericModel +""" + clear(s::AM) + +Clears or resets the state of the given `AM` (Atmospheric Model) instance `s`. +# Arguments +- `s::AM`: An instance of the `AM` (Atmospheric Model) struct containing atmospheric parameters. + +# Returns +nothing +""" function clear(s::AM) s.rho_zero_temp = (15.0 - ABS_ZERO) / (s.set.temp_ref - ABS_ZERO) * s.set.rho_0 + nothing end @inline function fastexp(x) From 4d8b75b7ab16b82e3149bf0c7053ce28ec57ca6c Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:17:58 +0200 Subject: [PATCH 07/22] More docu --- docs/src/api.md | 5 +---- src/AtmosphericModels.jl | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/src/api.md b/docs/src/api.md index 192cfc5..d43e60f 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -15,12 +15,9 @@ AtmosphericModel ## Functions ### Exported functions -```julia -calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) -``` - ```@docs clear calc_rho +calc_wind_factor get_wind ``` \ No newline at end of file diff --git a/src/AtmosphericModels.jl b/src/AtmosphericModels.jl index 748ffde..80e7c04 100644 --- a/src/AtmosphericModels.jl +++ b/src/AtmosphericModels.jl @@ -173,6 +173,20 @@ function calc_wind_factor6(s::AM, height) evalpoly(1/height, (1.0, 1735.2333827029918, 279373.0012683715)) end +""" + calc_wind_factor(am::AM, height; profile_law::Int64=am.set.profile_law) + +Calculates the wind factor at a given `height` using the specified wind profile law. + +# Arguments +- `am::AM`: An instance of the `AM` type containing atmospheric model parameters. +- `height`: The height (in meters) at which to calculate the wind factor. +- `profile_law::Int64`: (Optional) The wind profile law to use for the calculation. + Defaults to `am.set.profile_law`. + +# Returns +- The wind factor at the specified height as determined by the chosen profile law. +""" @inline function calc_wind_factor(am::AM, height, profile_law::Int64=am.set.profile_law) if profile_law == 1 calc_wind_factor1(am, height) From b9f8d251f171be982d8fdbcb5becd28000b2dd66 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:27:01 +0200 Subject: [PATCH 08/22] Update docu --- docs/src/api.md | 4 +++- src/AtmosphericModels.jl | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/src/api.md b/docs/src/api.md index d43e60f..dc76e7b 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -8,9 +8,11 @@ CurrentModule = AtmosphericModels ### Exported types ```julia -AtmosphericModel @enum ProfileLaw EXP=1 LOG=2 EXPLOG=3 FAST_EXP=4 FAST_LOG=5 FAST_EXPLOG=6 ``` +```@docs +AtmosphericModel +``` ## Functions diff --git a/src/AtmosphericModels.jl b/src/AtmosphericModels.jl index 80e7c04..0d2898f 100644 --- a/src/AtmosphericModels.jl +++ b/src/AtmosphericModels.jl @@ -35,6 +35,11 @@ end mutable struct AtmosphericModel Struct that is storing the settings and the state of the atmosphere. + +# Fields +- set::Settings: The Settings struct +- `rho_zero_temp` +- wf::Union{WindField, Nothing}: The 3D windfield or `nothing` """ Base.@kwdef mutable struct AtmosphericModel set::Settings @@ -61,7 +66,7 @@ Clears or resets the state of the given `AM` (Atmospheric Model) instance `s`. - `s::AM`: An instance of the `AM` (Atmospheric Model) struct containing atmospheric parameters. # Returns -nothing +- nothing """ function clear(s::AM) s.rho_zero_temp = (15.0 - ABS_ZERO) / (s.set.temp_ref - ABS_ZERO) * s.set.rho_0 From 89e5b1fae5ffe637da14f8805c1974e040e832f8 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:37:50 +0200 Subject: [PATCH 09/22] API complete --- docs/src/api.md | 5 ++--- src/AtmosphericModels.jl | 12 ++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/src/api.md b/docs/src/api.md index dc76e7b..6b11173 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -7,11 +7,10 @@ CurrentModule = AtmosphericModels ## Types ### Exported types -```julia -@enum ProfileLaw EXP=1 LOG=2 EXPLOG=3 FAST_EXP=4 FAST_LOG=5 FAST_EXPLOG=6 -``` ```@docs +ProfileLaw AtmosphericModel +AtmosphericModel(set::Settings; nowindfield::Bool=false) ``` ## Functions diff --git a/src/AtmosphericModels.jl b/src/AtmosphericModels.jl index 0d2898f..254527f 100644 --- a/src/AtmosphericModels.jl +++ b/src/AtmosphericModels.jl @@ -47,6 +47,18 @@ Base.@kwdef mutable struct AtmosphericModel wf::Union{WindField, Nothing} = nothing end +""" + AtmosphericModel(set::Settings; nowindfield::Bool=false) + +Constructs an `AtmosphericModel` using the provided `Settings`. + +# Arguments +- `set::Settings`: The settings object containing configuration parameters for the atmospheric model. +- `nowindfield::Bool=false`: Optional keyword argument. If `true`, the wind field will not be loaded. + +# Returns +- An instance of `AtmosphericModel` configured according to the provided settings. +""" function AtmosphericModel(set::Settings; nowindfield::Bool=false) am = AtmosphericModel(set=set) if set.use_turbulence > 0 && !nowindfield From 3bfac7400aef12a966d04291a36d591e8fb0b20c Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:47:12 +0200 Subject: [PATCH 10/22] Add docu --- docs/src/api.md | 2 ++ src/windfield.jl | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/src/api.md b/docs/src/api.md index 6b11173..2de6312 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -21,4 +21,6 @@ clear calc_rho calc_wind_factor get_wind +new_windfield +new_windfields ``` \ No newline at end of file diff --git a/src/windfield.jl b/src/windfield.jl index 906cdd0..6258cfe 100644 --- a/src/windfield.jl +++ b/src/windfield.jl @@ -345,7 +345,7 @@ end """ new_windfield(am::AtmosphericModel, v_wind_gnd; prn=true) -Create a new wind field object using the given ground wind velocity vector `v_wind_gnd`. +Create a new wind field file using the given, scalar ground wind velocity `v_wind_gnd`. # Parameters - `am::AtmosphericModel`: The atmospheric model for which the wind field is created. @@ -353,7 +353,7 @@ Create a new wind field object using the given ground wind velocity vector `v_wi - `prn`: Optional boolean flag to control printing of progress messages (default is `true`). # Returns -nothing +- nothing """ function new_windfield(am::AtmosphericModel, v_wind_gnd; prn=true) Random.seed!(1234) @@ -368,13 +368,14 @@ function new_windfield(am::AtmosphericModel, v_wind_gnd; prn=true) end """ - new_windfields(am::AtmosphericModel) + new_windfields(am::AtmosphericModel; prn=true) Create and initialize new wind fields for all ground wind speeds, defined in `am.set.v_wind_gnds` and save them for the given `AtmosphericModel` instance `am`. # Arguments - `am::AtmosphericModel`: The atmospheric model for which wind fields are to be generated. +- `prn`: Optional boolean flag to control printing of progress messages (default is `true`). # Returns - nothing From 05d2d2f4b6474cc6160cfb21d52aa15476e5df9c Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sat, 5 Jul 2025 23:52:22 +0200 Subject: [PATCH 11/22] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5052098..f406696 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,4 +4,5 @@ - BREAKING: When constructing an atmospheric model, you MUST pass the parameter set::Settings. This ensures that all parts of the simulation use the same settings struct, and that you can run different simulations with different settings in parallel. ## Added -- The function `get_wind(am, x, y, z, t)` which returns a wind vector for the given position and time. It creates a 3D wind field if it does not exist in the data folder. The parameters of this wind field are configured in `settings.yaml`. \ No newline at end of file +- The function `get_wind(am, x, y, z, t)` which returns a wind vector for the given position and time. It creates a 3D wind field if it does not exist in the data folder. The parameters of this wind field are configured in `settings.yaml`. +- Documenter generated documentation. \ No newline at end of file From 0fb209e47edb857710cdbc62a769114344f453f0 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 00:06:46 +0200 Subject: [PATCH 12/22] Update docu --- docs/src/api.md | 6 +++++- src/windfield.jl | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/src/api.md b/docs/src/api.md index 2de6312..1587f79 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -15,12 +15,16 @@ AtmosphericModel(set::Settings; nowindfield::Bool=false) ## Functions -### Exported functions +### Wind shear and air density calculation ```@docs clear calc_rho calc_wind_factor +``` +### Wind turbulence calculation +```@docs get_wind +rel_turbo new_windfield new_windfields ``` \ No newline at end of file diff --git a/src/windfield.jl b/src/windfield.jl index 6258cfe..34bfab0 100644 --- a/src/windfield.jl +++ b/src/windfield.jl @@ -50,6 +50,18 @@ function calc_sigma1(am, v_wind_gnd) am.set.i_ref * (0.75 * v_height + 5.6) end +""" + rel_turbo(am::AtmosphericModel, v_wind = am.set.v_wind) + +Find the closest relative turbulence value for a given ground wind speed. + +# Arguments +- `am::AtmosphericModel`: The atmospheric model instance containing relevant parameters. +- `v_wind`: (Optional) The wind velocity to use for the calculation. Defaults to `am.set.v_wind`. + +# Returns +- The computed relative turbulence value. +""" function rel_turbo(am::AtmosphericModel, v_wind = am.set.v_wind) # Find the closest relative turbulence value for a given ground wind speed min_dist, idx = findmin(abs.(am.set.v_wind_gnds .- v_wind)) From 0766a4b19b532eacc05c664c00a0c7b8c6b396ce Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 00:14:52 +0200 Subject: [PATCH 13/22] Update CI.yml --- .github/workflows/CI.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8ed9dbb..48c77b0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -54,3 +54,23 @@ jobs: - uses: codecov/codecov-action@v5 with: files: lcov.info + docs: + name: Documentation + runs-on: ubuntu-latest + timeout-minutes: 40 + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + - uses: julia-actions/cache@v2 + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-docdeploy@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} + - run: | + julia --project=docs -e ' + using Documenter: DocMeta, doctest + using AtmosphericModels + DocMeta.setdocmeta!(AtmosphericModels, :DocTestSetup, :(using AtmosphericModels); recursive=true) + doctest(AtmosphericModels)' + From b1c2c40c8e5dcfbbbe9b2de6ad036bf826bf7c62 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 05:37:14 +0200 Subject: [PATCH 14/22] Remove KiteUtils --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 99bde98..4783c0d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,4 +1,4 @@ -using KiteUtils, AtmosphericModels +using AtmosphericModels using Pkg if ("TestEnv" ∈ keys(Pkg.project().dependencies)) if ! ("Documents" ∈ keys(Pkg.project().dependencies)) From ccfba6db5753d65614c9ad3c200666734613e676 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 05:41:35 +0200 Subject: [PATCH 15/22] Next try --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 4783c0d..dfc5388 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,7 +1,7 @@ using AtmosphericModels using Pkg if ("TestEnv" ∈ keys(Pkg.project().dependencies)) - if ! ("Documents" ∈ keys(Pkg.project().dependencies)) + if ! ("Documenter" ∈ keys(Pkg.project().dependencies)) using TestEnv; TestEnv.activate() end end From 084b7578871495744ba824dd64124815b606589a Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 05:51:25 +0200 Subject: [PATCH 16/22] Add file to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 59a51f7..8a9a7d0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ examples/Manifest.toml examples/Manifest-v1.10.toml examples/Manifest-v1.11.toml docs/build +docs/Manifest.toml From 5582da53bc9a5d0f7cb40b9eebf988d95157420c Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 05:51:39 +0200 Subject: [PATCH 17/22] Add Project.toml --- docs/Project.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/Project.toml diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 0000000..c2770b8 --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,3 @@ +[deps] +AtmosphericModels = "c59cac55-771d-4f45-b14d-1c681463a295" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" From 3331c69a6574aaa3e0f3ba26090afddefc23b4fd Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 06:04:27 +0200 Subject: [PATCH 18/22] Enable push_preview --- docs/make.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/make.jl b/docs/make.jl index dfc5388..43f7675 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -30,4 +30,5 @@ makedocs(; deploydocs(; repo="github.com/OpenSourceAWE/AtmosphericModels.jl", devbranch="main", + push_preview=true, ) From 37ce6ae18c59ef128f3451d53b759e3a06508352 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 06:39:31 +0200 Subject: [PATCH 19/22] Update settings.yaml --- data/settings.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/settings.yaml b/data/settings.yaml index 37b6e43..f8cfab3 100644 --- a/data/settings.yaml +++ b/data/settings.yaml @@ -108,7 +108,7 @@ winch: environment: v_wind: 5.324 # wind speed at reference height [m/s] - v_wind_ref: [5.324, 0.0] # wind speed vector at reference height [m/s] + upwind_dir: -90.0 # upwind direction [deg] temp_ref: 15.0 # temperature at reference height [°C] height_gnd: 0.0 # height of groundstation above see level [m] h_ref: 6.0 # reference height for the wind speed [m] From 2aabb812783895aea9a9b451e9fbd40d561a7d93 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 07:13:55 +0200 Subject: [PATCH 20/22] Add settings.md --- docs/make.jl | 1 + docs/src/settings.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 docs/src/settings.md diff --git a/docs/make.jl b/docs/make.jl index 43f7675..fc246b3 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -24,6 +24,7 @@ makedocs(; pages=[ "Home" => "index.md", "API" => "api.md", + "Settings" => "settings.md", ], ) diff --git a/docs/src/settings.md b/docs/src/settings.md new file mode 100644 index 0000000..0684bc2 --- /dev/null +++ b/docs/src/settings.md @@ -0,0 +1,32 @@ +```@meta +CurrentModule = AtmosphericModels +``` + +The parameters af the atmospheric model can be configured in the section `environment` of the `settings.yaml` file in the `data` folder. + +The file `system.yaml` specifies which `yaml` files are used to configure +the current project. + +```yaml +environment: + v_wind: 5.324 # wind speed at reference height [m/s] + upwind_dir: -90.0 # upwind direction [deg] + temp_ref: 15.0 # temperature at reference height [°C] + height_gnd: 0.0 # height of groundstation above see level [m] + h_ref: 6.0 # reference height for the wind speed [m] + + rho_0: 1.225 # air density at zero height and 15 °C [kg/m³] + alpha: 0.234 # exponent of the wind profile law + z0: 0.0002 # surface roughness [m] + profile_law: 1 # 1=EXP, 2=LOG, 3=EXPLOG, 4=FAST_EXP, 5=FAST_LOG, 6=FAST_EXPLOG + # the following parameters are for calculating the turbulent wind field using the Mann model + use_turbulence: 1.0 # turbulence intensity relative to Cabauw, NL + v_wind_gnds: [3.483, 5.324, 8.163] # wind speeds at ref height for calculating the turbulent wind field [m/s] + avg_height: 200.0 # average height during reel out [m] + rel_turbs: [0.342, 0.465, 0.583] # relative turbulence at the v_wind_gnds + i_ref: 0.14 # is the expected value of the turbulence intensity at 15 m/s. + v_ref: 42.9 # five times the average wind speed in m/s at hub height over the full year [m/s] + # Cabauw: 8.5863 m/s * 5.0 = 42.9 m/s + height_step: 2.0 # use a grid with 2m resolution in z direction [m] + grid_step: 2.0 # grid resolution in x and y direction [m] +``` \ No newline at end of file From 6e4d7d23083ff46639f45134155544c08d05352f Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 07:47:50 +0200 Subject: [PATCH 21/22] Update docu --- docs/src/api.md | 10 ++++++++++ docs/src/settings.md | 14 +++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/src/api.md b/docs/src/api.md index 1587f79..eed421a 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -3,6 +3,16 @@ CurrentModule = AtmosphericModels ``` ## Introduction +Most functions need an instance of the struct `AtmosphericModel` as first parameter, +which can be created using the following code: +```julia +using AtmosphericModels, KiteUtils + +set_data_path("data") +set = load_settings("system.yaml") +am::AtmosphericModel = AtmosphericModel(set) +``` +This requires that the files `system.yaml` and `settings.yaml` exist in the folder `data`. See also [Settings](@ref). ## Types diff --git a/docs/src/settings.md b/docs/src/settings.md index 0684bc2..46e0fd7 100644 --- a/docs/src/settings.md +++ b/docs/src/settings.md @@ -2,11 +2,20 @@ CurrentModule = AtmosphericModels ``` +## Settings The parameters af the atmospheric model can be configured in the section `environment` of the `settings.yaml` file in the `data` folder. The file `system.yaml` specifies which `yaml` files are used to configure the current project. +### Example for system.yaml +```yaml +system: + project: "settings.yaml" # simulator settings +``` +Often additional `yaml` files, for example for the controller settings are used. + +### Example for settings.yaml ```yaml environment: v_wind: 5.324 # wind speed at reference height [m/s] @@ -29,4 +38,7 @@ environment: # Cabauw: 8.5863 m/s * 5.0 = 42.9 m/s height_step: 2.0 # use a grid with 2m resolution in z direction [m] grid_step: 2.0 # grid resolution in x and y direction [m] -``` \ No newline at end of file +``` + +## Remarks +- If the parameter `use_turbulence` is zero, no windfield is loaded. \ No newline at end of file From ce3680f3781af1247ad0f0f4f9d22573a7abf4c4 Mon Sep 17 00:00:00 2001 From: Uwe Fechner Date: Sun, 6 Jul 2025 08:13:47 +0200 Subject: [PATCH 22/22] Update API --- docs/src/api.md | 4 ++++ src/AtmosphericModels.jl | 26 +++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/src/api.md b/docs/src/api.md index eed421a..fd4f4bf 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -22,6 +22,10 @@ ProfileLaw AtmosphericModel AtmosphericModel(set::Settings; nowindfield::Bool=false) ``` +### Private types +```@docs +WindField +``` ## Functions diff --git a/src/AtmosphericModels.jl b/src/AtmosphericModels.jl index 254527f..57e843a 100644 --- a/src/AtmosphericModels.jl +++ b/src/AtmosphericModels.jl @@ -13,6 +13,30 @@ export new_windfield, new_windfields, get_wind const ABS_ZERO = -273.15 const SRL = StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64} +""" + struct WindField + +Struct that is storing a 3D model of wind vectors of the atmosphere. The Fields +x, y and z store the grid coordinates, the fields u, v and w the wind turbulence +vectors. + +# Fields +- x_max::Float64 = NaN +- x_min::Float64 = NaN +- y_max::Float64 = NaN +- y_min::Float64 = NaN +- z_max::Float64 = NaN +- z_min::Float64 = NaN +- last_speed::Float64 = 0.0 +- valid::Bool = false +- x::Union{SRL, Array{Float64, 3}} +- y::Union{SRL, Array{Float64, 3}} +- z::Union{SRL, Array{Float64, 3}} +- u::Array{Float64, 3} +- v::Array{Float64, 3} +- w::Array{Float64, 3} +- param::Vector{Float64} = [0, 0] # [alpha, `v_wind_gnd`] +""" Base.@kwdef struct WindField x_max::Float64 = NaN x_min::Float64 = NaN @@ -39,7 +63,7 @@ Struct that is storing the settings and the state of the atmosphere. # Fields - set::Settings: The Settings struct - `rho_zero_temp` -- wf::Union{WindField, Nothing}: The 3D windfield or `nothing` +- wf::Union{WindField, Nothing}: The 3D [`WindField`](@ref) or `nothing` """ Base.@kwdef mutable struct AtmosphericModel set::Settings