From 90b1689a2f35c9e5cca62ca2bd755bf79e28391e Mon Sep 17 00:00:00 2001 From: Mauco03 <marco.gaibotti@skywarder.eu> Date: Sun, 20 Apr 2025 21:17:15 +0200 Subject: [PATCH] [coeff-transport][Wind] Added internal griddedInterpolant to wind --- classes/misc/Wind.m | 116 ++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/classes/misc/Wind.m b/classes/misc/Wind.m index f3eb9a9..f3d6707 100644 --- a/classes/misc/Wind.m +++ b/classes/misc/Wind.m @@ -9,6 +9,7 @@ classdef Wind < Config % - mission: Mission, mission object % - varIn: (optional) config source. Alternative to config.m % file + properties(Dependent) altitudes (1, :) @@ -25,6 +26,9 @@ classdef Wind < Config end properties(Access = private) + isReady (1, 1) logical % true if all properties are set + dataInerpolant (1, 1) griddedInterpolant % [-] Interpolates [magnitude, azimuth, elevation] + ALTITUDES MAGNITUDE_DISTRIBUTION = '' @@ -41,77 +45,71 @@ classdef Wind < Config elevation magnitude end - - properties(Access = private) - checks (1, 3) logical % true if #[magnitude, azimuth, elevation] == #altitudes - end properties(Constant, Access = protected) configName = 'windConfig.m' variableName = 'windCustom' end - methods % Getters / Setters - function obj = set.altitudes(obj, value) - if length(value) ~= length(obj.ALTITUDES) - obj.ALTITUDES = value; - obj.magnitude = obj.updateDistribution(obj.MAGNITUDE_DISTRIBUTION, obj.MAGNITUDE_PARAMETERS); - obj.azimuth = obj.updateDistribution(obj.AZIMUTH_DISTRIBUTION, obj.AZIMUTH_PARAMETERS); - obj.elevation = obj.updateDistribution(obj.ELEVATION_DISTRIBUTION, obj.ELEVATION_PARAMETERS); - else - obj.ALTITUDES = value; - end + methods % Getters + function value = get.altitudes(obj), value = obj.ALTITUDES; end + + function value = get.magnitudeDistribution(obj), value = obj.MAGNITUDE_DISTRIBUTION; end + function value = get.azimuthDistribution(obj), value = obj.AZIMUTH_DISTRIBUTION; end + function value = get.elevationDistribution(obj), value = obj.ELEVATION_DISTRIBUTION; end + + function value = get.magnitudeParameters(obj), value = obj.MAGNITUDE_PARAMETERS; end + function value = get.azimuthParameters(obj), value = obj.AZIMUTH_PARAMETERS; end + function value = get.elevationParameters(obj), value = obj.ELEVATION_PARAMETERS; end + end - obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES); - obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES); - obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES); + methods % Setters + function obj = set.altitudes(obj, value) + obj.ALTITUDES = value; + obj = obj.updateAll(); end function obj = set.magnitudeDistribution(obj, value) obj.MAGNITUDE_DISTRIBUTION = value; + obj.isReady = obj.checkProperties(); obj.magnitude = obj.updateDistribution(value, obj.MAGNITUDE_PARAMETERS); - obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES); + obj = obj.updateInterpolant(); end function obj = set.magnitudeParameters(obj, value) obj.MAGNITUDE_PARAMETERS = value; + obj.isReady = obj.checkProperties(); obj.magnitude = obj.updateDistribution(obj.MAGNITUDE_DISTRIBUTION, value); - obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES); + obj = obj.updateInterpolant(); end function obj = set.azimuthDistribution(obj, value) obj.AZIMUTH_DISTRIBUTION = value; + obj.isReady = obj.checkProperties(); obj.azimuth = obj.updateDistribution(value, obj.AZIMUTH_PARAMETERS); - obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES); + obj = obj.updateInterpolant(); end function obj = set.azimuthParameters(obj, value) obj.AZIMUTH_PARAMETERS = value; + obj.isReady = obj.checkProperties(); obj.azimuth = obj.updateDistribution(obj.AZIMUTH_DISTRIBUTION, value); - obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES); + obj = obj.updateInterpolant(); end function obj = set.elevationDistribution(obj, value) obj.ELEVATION_DISTRIBUTION = value; + obj.isReady = obj.checkProperties(); obj.elevation = obj.updateDistribution(value, obj.ELEVATION_PARAMETERS); - obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES); + obj = obj.updateInterpolant(); end function obj = set.elevationParameters(obj, value) obj.ELEVATION_PARAMETERS = value; + obj.isReady = obj.checkProperties(); obj.elevation = obj.updateDistribution(obj.ELEVATION_DISTRIBUTION, value); - obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES); + obj = obj.updateInterpolant(); end - - function value = get.altitudes(obj), value = obj.ALTITUDES; end - - function value = get.magnitudeDistribution(obj), value = obj.MAGNITUDE_DISTRIBUTION; end - function value = get.azimuthDistribution(obj), value = obj.AZIMUTH_DISTRIBUTION; end - function value = get.elevationDistribution(obj), value = obj.ELEVATION_DISTRIBUTION; end - - function value = get.magnitudeParameters(obj), value = obj.MAGNITUDE_PARAMETERS; end - function value = get.azimuthParameters(obj), value = obj.AZIMUTH_PARAMETERS; end - function value = get.elevationParameters(obj), value = obj.ELEVATION_PARAMETERS; end end methods @@ -123,18 +121,8 @@ classdef Wind < Config obj@Config(mission, varIn); end - function obj = updateAll(obj) - obj.magnitude = obj.updateDistribution(obj.MAGNITUDE_DISTRIBUTION, obj.MAGNITUDE_PARAMETERS); - obj.azimuth = obj.updateDistribution(obj.AZIMUTH_DISTRIBUTION, obj.AZIMUTH_PARAMETERS); - obj.elevation = obj.updateDistribution(obj.ELEVATION_DISTRIBUTION, obj.ELEVATION_PARAMETERS); - - obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES); - obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES); - obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES); - end - function [uw, vw, ww] = getVels(obj, z) - if ~all(obj.checks) + if ~obj.isReady error(['Parameters and distributions must be the same ' ... 'size as altitudes or scalar']); end @@ -144,18 +132,52 @@ classdef Wind < Config vw = round( - obj.magnitude * sin(obj.azimuth) * cos(obj.elevation), 6); ww = round( - obj.magnitude * (-sin(obj.elevation)), 6); else - mag = interpLinear(obj.altitudes, obj.magnitude, z, true); - az = interpLinear(obj.altitudes, obj.azimuth, z, true); - el = interpLinear(obj.altitudes, obj.elevation, z, true); + data = obj.dataInerpolant(z); + mag = data(1); az = data(2); el = data(3); uw = round( - mag * cos(az) * cos(el), 6); vw = round( - mag * sin(az) * cos(el), 6); ww = round( - mag * (-sin(el)), 6); end end + + function obj = updateAll(obj) + obj.magnitude = obj.updateDistribution(obj.MAGNITUDE_DISTRIBUTION, obj.MAGNITUDE_PARAMETERS); + obj.azimuth = obj.updateDistribution(obj.AZIMUTH_DISTRIBUTION, obj.AZIMUTH_PARAMETERS); + obj.elevation = obj.updateDistribution(obj.ELEVATION_DISTRIBUTION, obj.ELEVATION_PARAMETERS); + + obj.isReady = obj.checkProperties(); + obj = obj.updateInterpolant(); + end + + function obj = updateInterpolant(obj) + % UPDATEINTERPOLANT: Interpolates [magnitude; azimuth; elevation] based on altitude + % + % Returns: + % - interpolant: griddedInterpolant for [magnitude; azimuth; elevation] + + if ~obj.isReady, return; end + if isscalar(obj.ALTITUDES), return; end + + % Prepare data for interpolation + data = [obj.magnitude; obj.azimuth; obj.elevation]; + gridVec = obj.ALTITUDES; + + % Create gridded interpolant + obj.dataInerpolant = griddedInterpolant(gridVec, data', 'linear', 'nearest'); + end end methods(Access = private) + function ready = checkProperties(obj) + % Check if STATIC, DYNAMIC, GEOMETRY, and STATE are non-empty + + ready = ... + length(obj.magnitude) == length(obj.ALTITUDES) && ... + length(obj.azimuth) == length(obj.ALTITUDES) && ... + length(obj.elevation) == length(obj.ALTITUDES); + end + function vec = updateDistribution(obj, dist, parameters) s = length(obj.ALTITUDES); vec = []; -- GitLab