diff --git a/@BearImp/BearImp.m b/@BearImp/BearImp.m index 9e51a353cb7eb2da5ce48e480e807908bd0a232c..25dbf68b8a36bfa9f12cf6d0e83d9fb2137bc488 100644 --- a/@BearImp/BearImp.m +++ b/@BearImp/BearImp.m @@ -13,8 +13,8 @@ classdef BearImp < handle & matlab.mixin.Copyable resolutionPerRotation (1,1) double {mustBeNonnegative, mustBeInteger} % Anzahl an Zwischenschritten des Winkels psi innerhalb einer 360°-Drehung L (1,1) struct % Lagerparameter (gegeben) S (1,1) struct % Schmierstoffparameter (gegeben) - method (1,1) struct % struct der Rechenmethoden mit möglichen Feldern T,R,G,B,H,Z AddOn (1,1) struct % Installierte AddOns + method (1,1) BearImpOptions % BearImpOptions-Objekt mit gewählten Optionen der Rechenmethoden % Structs mit Berechnungsparamtern @@ -31,9 +31,9 @@ classdef BearImp < handle & matlab.mixin.Copyable properties (Access = private) % Eingangsparameter Speicher privateInputParameters = struct('F_r',nan,'F_a',nan,'omega',nan,'T_Oil',nan,'psi',nan,'psi_calc',nan,'psi_all',nan,'ind_psi_all',nan,'f',nan,'L',struct,'S',struct,'resolutionPerRotation',nan) - privateMethod = struct privateResults = struct('T',struct,'R',struct,'G',struct,'B',struct,'H',struct,'C',struct,'Z',struct) privateAddOn = struct('Parallel_Computing_Toolbox', 'auto', 'Optimization_Toolbox', 'auto') + privateMethod = BearImpOptions end properties (Access = public) @@ -76,7 +76,16 @@ classdef BearImp < handle & matlab.mixin.Copyable obj.resolutionPerRotation = 360; end end - + addlistener(obj.method,'optionChanged',@(src,event) obj.methodChangedFcn(src,event)); + end + end + + methods + function methodChangedFcn(obj,src,~) + for mc = src.optionsLastChanged + obj.up2date.(mc{:}) = false; + end + src.optionsLastChanged = {}; end end @@ -200,25 +209,15 @@ classdef BearImp < handle & matlab.mixin.Copyable obj.up2date.C = false; obj.privateInputParameters.S = S; end - function set.method(obj,method) - possibleMethods.check(method,true); - somethingChanged = false; - for ii = {'T','R','G','B','H','C','Z'} - if isfield(obj.method,ii) && isfield (method,ii) - if ~strcmp(obj.method.(ii{1}), method.(ii{1})) - obj.up2date.(ii{1}) = false; - somethingChanged = true; - end - elseif isfield(obj.method,ii{1}) || isfield (method,ii{1}) - obj.up2date.(ii{1}) = false; - somethingChanged = true; + function set.method(obj,newMethod) + oldMethod = obj.privateMethod.copy; + obj.privateMethod = newMethod; + [isEqual,methodsChanged] = eq(oldMethod,newMethod); + if ~isEqual + for mc = methodsChanged + obj.up2date.(mc{:}) = false; end end - if somethingChanged - obj.privateMethod = method; - else - warning('Keine Methode geändert') - end end function set.up2date(obj,up2date) @@ -346,6 +345,9 @@ classdef BearImp < handle & matlab.mixin.Copyable end + end + function method = get.method(obj) + method = obj.privateMethod; end function L = get.L(obj) L = obj.privateInputParameters.L; @@ -353,9 +355,6 @@ classdef BearImp < handle & matlab.mixin.Copyable function S = get.S(obj) S = obj.privateInputParameters.S; end - function method = get.method(obj) - method = obj.privateMethod; - end function T = get.T(obj) T = obj.privateResults.T; end @@ -407,5 +406,9 @@ classdef BearImp < handle & matlab.mixin.Copyable feval(functionHandle,obj(ii)) end end + function cp = copyElement(obj) + cp = copyElement@matlab.mixin.Copyable(obj); + cp.method = obj.method.copy; % creat a deep copy of the method + end end end \ No newline at end of file diff --git a/@BearImp/calcCap.m b/@BearImp/calcCap.m index d391d9afcd16330bdad8f6057326d9a9b71996ac..c2c2160f560fd586f46eb61a0c98afbf27a56ba2 100644 --- a/@BearImp/calcCap.m +++ b/@BearImp/calcCap.m @@ -17,7 +17,7 @@ assert(obj.up2date.B,'Belastungsverteilung noch nicht berechnet') assert(obj.up2date.H,'Schmierfilmdicke noch nicht berechnet') L = obj.L; S = obj.S; T = obj.T; G = obj.G; B = obj.B; H = obj.H; AddOn = obj.AddOn; psi = obj.psi; C = obj.C; -method = possibleMethods.addDefault(obj.method).C; +C.method = obj.method.C; if ~isfield(C,'k_C') C.k_C = 1; end @@ -62,7 +62,7 @@ for posBall_conductive=1:L.numberOfConductiveBalls tempR_li = G.R_li(ballMaterialInd(posBall_conductive)); tempR_la = G.R_la(ballMaterialInd(posBall_conductive)); tempR_RE = G.R_RE(ballMaterialInd(posBall_conductive)); - if any(strcmp(method.outsideArea,{'Schneider_k_c','Schneider_k_vh'})) + if any(C.method.outsideArea == {'Schneider_k_c','Schneider_k_vh'}) tempG = H.G (:,:,posBall_conductive); tempW = H.W (:,:,posBall_conductive); end @@ -87,12 +87,12 @@ for posBall_conductive=1:L.numberOfConductiveBalls C.phi_2i = asin(L.B_i/G.D_RE(ballMaterialInd(posBall_conductive))); C.phi_2a = asin(L.B_a/G.D_RE(ballMaterialInd(posBall_conductive))); - if any([strcmp(method.unloadedRE,{'Leander_Radial','LeanderSteffen'}) strcmp(method.outsideArea,{'Leander_Radial','LeanderSteffen'})]) + if any([C.method.unloadedRE=={'Leander_Radial','LeanderSteffen'} C.method.outsideArea=={'Leander_Radial','LeanderSteffen'}]) calcZg end if any(B.noContactInd,'all') % Wenn Kraftfreie Wälzkörper vorhanden - switch method.unloadedRE + switch C.method.unloadedRE case 'neglect' case 'stateOfTheArt' stateOfTheArt(find(contactInd==0)) @@ -112,7 +112,7 @@ for posBall_conductive=1:L.numberOfConductiveBalls end end - switch method.outsideArea + switch C.method.outsideArea case 'neglect' case 'k-factor' C.C_out(:,contactInd,posBall_conductive) = (C.k_C-1) .* C.C_Hertz(:,contactInd,posBall_conductive); @@ -239,7 +239,7 @@ end function tobias_steffen(indices) C.h_i = @(alpha,beta,ii) (sqrt(tempR_li^2 - C.DeltaR_i(ii)^2*sin(alpha).^2) - C.DeltaR_i(ii)*cos(alpha)) ./ cos(beta) - tempR_RE; C.h_a = @(alpha,beta,ii) (sqrt(tempR_la^2 - C.DeltaR_a(ii)^2*sin(alpha).^2) - C.DeltaR_a(ii)*cos(alpha)) ./ cos(beta) - tempR_RE; - if strcmp(method.unloadedRE,'TobiasSteffen_Kugelfläche') + if C.method.unloadedRE == 'TobiasSteffen_Kugelfläche' C.dA_i = @(~,beta,~) tempR_RE^2 * cos(beta); C.dA_a = C.dA_i; else diff --git a/@BearImp/calcFilm.m b/@BearImp/calcFilm.m index b734c6fea58d2c4852fa26412dc14b815189cce9..ed1de33d8f84a8d6f48d7e92a8215f3fc9670a40 100644 --- a/@BearImp/calcFilm.m +++ b/@BearImp/calcFilm.m @@ -35,7 +35,7 @@ end L=obj.L; S = obj.S; T = obj.T; G = obj.G; B = obj.B; T_Oil = obj.T_Oil; omega = obj.omega; H = struct; -method = possibleMethods.addDefault(obj.method).H; +H.method = obj.method.H; %% Berechnung @@ -71,20 +71,20 @@ H.W = Q_temp./(E_red_tmp .* R_x_temp.^2); H.L = H.G .* H.U.^0.25; H.M = H.W.*(2.*H.U).^(-3/4); -switch method +switch H.method case {'Hamrock/Dowson','Hamrock/Dowson_withoutThermCorr'} H.H_0 = 2.69 * H.G.^0.53 .* H.U.^0.67 .* H.W.^-0.067 .* (1-0.61*exp(-0.73.*G.k)); H.H_min = 3.63 * H.G.^0.49 .* H.U.^0.68 .* H.W.^-0.073 .* (1- exp(-0.68.*G.k)); H.h_0raw = H.H_0 .*R_x_temp; % without correction factors H.h_min = H.H_min.*R_x_temp; H.L_therm = T.eta_0 .* T.alpha_etaT .* H.u.^2 ./ (4*S.lambda); - if strcmp(method,'Hamrock/Dowson') + if H.method == 'Hamrock/Dowson' H.C_korr = 3.94 ./ (3.94 + H.L_therm.^0.62); else H.C_korr = 1; end - H.h_0 = H.h_0raw .*H.C_korr; - H.h_minth = H.h_min.*H.C_korr; + H.h_0 = H.h_0raw.*H.C_korr; + H.h_minth = H.h_min .*H.C_korr; case 'Moes' @@ -111,7 +111,7 @@ if isPreCalc return end -if strcmp(possibleMethods.addDefault(obj.method).B,'static') +if B.method == 'static' assert(ndims(H.h_0) <= 2,'h_0 must be two dimensional to calculate film for static load distribution') % probably obsolete B.s=zeros(2,B.numOfCagePositions,L.numberOfConductiveBalls); @@ -123,12 +123,12 @@ end % Überprüfen, ob die Schmierfilmberechnung innerhalb des vorgegeben % Bereichs liegt -switch method +switch H.method case {'Hamrock/Dowson','Hamrock/Dowson_withoutThermCorr'} rangeLoadParM = [25,500]; % Quelle: Non-Dimensional Groups, Marian 2020, Fig7 rangeViscParL = [5,15]; - if strcmp(possibleMethods.addDefault(obj.method).B,'dynamic') + if B.method == 'dynamic' warning('It is not recommended to use Hamrock/Dowson as lubricant film calculation when dynamic load calculation is selected, because the loads become very small outside the load range.') end case 'Moes' diff --git a/@BearImp/calcLoad.m b/@BearImp/calcLoad.m index fb2d85ece2c8dd94742d6b7de53af58b89de4e88..0c36b030e3a3bea51f2222af39f596ce7c153602 100644 --- a/@BearImp/calcLoad.m +++ b/@BearImp/calcLoad.m @@ -11,7 +11,7 @@ assert(obj.up2date.G,'Lagergeometrie in Abhängigkeit des Lagerspiels noch nicht L = obj.L; G = obj.G; F_r = obj.F_r; F_a = obj.F_a; AddOn = obj.AddOn; psi=obj.psi; B = struct; -B.method = possibleMethods.addDefault(obj.method).B; +B.method = obj.method.B; %% Berechnung if ~isnan(obj.psi_calc) @@ -20,7 +20,7 @@ end % delta_intp1 (the distance between the raceways) needs to be calculated % before delta_s in the dynamic case -if strcmp(B.method,'dynamic') +if B.method == 'dynamic' n_ir = obj.omega * 60 / (2*pi); n_ar = 0; B.v_cage = pi/60*G.d_m.*((1-cos(G.alpha)./(G.d_m./G.D_RE)).*n_ir./2+(1+cos(G.alpha)./(G.d_m./G.D_RE)).*n_ar./2); %Umfangsgeschwindigkeit des Käfigs [m/s] Brändlein S.88; Dowson u_i/o/c S.58 @@ -80,7 +80,7 @@ else end end -if strcmp(B.method,'dynamic') +if B.method == 'dynamic' assert(any(max(B.Q_intp1) > max(B.Q) & min(B.Q_intp1) < min(B.Q)), 'The interpolated lubricant film thicknesses are extrapolated outside the calculated range! This leads to inaccurate results.') end @@ -93,7 +93,7 @@ for posBall_conductive=1:L.numberOfConductiveBalls (round((L.IndBall_conductive(posBall_conductive)-1)*B.numOfCagePositions/L.Z)))]; % intersectionBall (intersection of Ball and inner/outer racerway) - if strcmp(B.method,'static') % static assumption: Ball in middle of gap + if B.method == 'static' % static assumption: Ball in middle of gap for IndPosBearing=1:B.numOfCagePositions deltaXYZ = deflectionForXYZ(L,G,L.IndBall_conductive(posBall_conductive),B.delta_s(:,IndPosBearing),B.psi_conductive(posBall_conductive,IndPosBearing)); B.intersectionBall(1,IndPosBearing,posBall_conductive) = (deltaXYZ - G.D_RE(L.RE_order_num(posBall_conductive)))./2; diff --git a/@BearImp/calcLub.m b/@BearImp/calcLub.m index 79b871500ac4c612074cce797ea8076ce27ff8ce..53d45ac22874d8eb5704f13a977e4aaa6ad38709 100644 --- a/@BearImp/calcLub.m +++ b/@BearImp/calcLub.m @@ -10,7 +10,7 @@ assert(obj.up2date.S,'Schmierstoff nicht gesetzt') S = obj.S; T_Oil = obj.T_Oil; T = struct; -T.method = possibleMethods.addDefault(obj.method).T; +T.method = obj.method.T; %% Berechnung T.rho = @(theta) S.rho_15.*(1 - S.alpha_rho.*(theta-15)); diff --git a/BearImpOptions.m b/BearImpOptions.m new file mode 100644 index 0000000000000000000000000000000000000000..4e4558a504d40195593bb4b5d27d764570975a57 --- /dev/null +++ b/BearImpOptions.m @@ -0,0 +1,282 @@ +classdef BearImpOptions < handle & dynamicprops & matlab.mixin.CustomDisplay & matlab.mixin.Copyable +% Enthält die zu verwendenden Berechnungsmethoden der einzelnen +% Berechnungsabschnitte (T, R, G, B, H, C), deren default-Methoden und +% eine Funktion zum überprüfen des Methodenstructs +% +% Limitations: Works for optionLevel 1:3 only (e.g. main.C.unloadedRE) and +% all options must be strings or char arrays + +% pmd Berechnungstool Lagerimpedanz +% Autor: Steffen Puchtler, Julius van der Kuip + + properties + optionName + optionLevel = 1 + optionChosen = 'default' + optionsLastChanged = {} + parent + end + + properties (Dependent) + possibleSubOptions (1,:) cell + hasSubSubOptions (1,1) logical + end + + events + optionChanged + end + + methods (Static) + function possibleOption = Possible + possibleOption.T = {'linear','Vogel'}; + possibleOption.B = {'static','dynamic'}; + possibleOption.H = {'Hamrock/Dowson','Hamrock/Dowson_withoutThermCorr','Moes'}; + possibleOption.C.unloadedRE = { 'neglect','stateOfTheArt', 'Leander_Parallel','Leander_Radial','LeanderSteffen','TobiasSteffen_Kugelfläche','TobiasSteffen_Laufbahnfläche','semianalytisch3D'}; + possibleOption.C.outsideArea = {'k-factor','neglect','stateOfTheArt','Schneider_k_c','Schneider_k_vh','Leander_Parallel','Leander_Radial','LeanderSteffen','TobiasSteffen_Kugelfläche','TobiasSteffen_Laufbahnfläche','semianalytisch3D'}; + end + + function defaultOption = Default + % Gibt ein Rechenmethoden-Struct mit den Default-Methoden aus + defaultOption.T = 'Vogel'; + defaultOption.B = 'dynamic'; + defaultOption.H = 'Hamrock/Dowson'; + defaultOption.C.unloadedRE = 'semianalytisch3D'; + defaultOption.C.outsideArea = 'semianalytisch3D'; + end + + function allCategories = AllCategories + allCategories = [{'main'} fieldnames(BearImpOptions.Possible)']; + mainNames = fieldnames(BearImpOptions.Possible); + for ii = 1:numel(mainNames) + if isstruct(BearImpOptions.Possible.(mainNames{ii})) + allCategories = [allCategories fieldnames(BearImpOptions.Possible.(mainNames{ii}))']; %#ok<AGROW> + end + end + end + end + + methods + function obj = BearImpOptions(optionName,parent) + arguments + optionName = 'main' + parent = []; + end + %mustBeMember(optionName,BearImpOptions.AllCategories) + + obj.optionName = optionName; + obj.parent = parent; + + if ~isempty(parent) + obj.optionLevel = parent.optionLevel + 1; + end + + if isempty(obj.possibleSubOptions) + return + end + + for sub = obj.possibleSubOptions + if obj.hasSubSubOptions + newProp = obj.addprop(sub{:}); + obj.(sub{:}) = BearImpOptions(sub{:},obj); + newProp.SetMethod = @(obj,optionChoice) obj.set_optionChosen(sub{:},optionChoice); + newProp.NonCopyable = false; + end + end + + if ~obj.hasSubSubOptions + newProp = obj.addprop('defaultOption'); + newProp.NonCopyable = false; + switch obj.optionLevel + case 2 + obj.defaultOption = BearImpOptions.Default.(obj.optionName); + case 3 + obj.defaultOption = BearImpOptions.Default.(obj.parent.optionName).(obj.optionName); + end + end + end + end + + methods + function charOut = char(obj) + if strcmp(obj.optionChosen,'default') && ~obj.hasSubSubOptions + charOut = obj.defaultOption; + else + charOut = obj.optionChosen; + end + end + + function stringOut = string(obj) + stringOut = string(char(obj)); + end + + function cellOut = cell(obj) + cellOut = {char(obj)}; + end + + function [logicalOut,diffs] = eq(obj,otherObj) + nargoutchk(0,2) + logicalOut = true; + diffs = {}; + if ischar(otherObj) || isstring(otherObj) || iscellstr(otherObj) + logicalOut = strcmp(char(obj),otherObj); + return + end + if ischar(obj) || isstring(obj) || iscellstr(obj) + logicalOut = strcmp(char(otherObj),obj); + return + end + try + if obj.hasSubSubOptions + for sub = obj.possibleSubOptions + if obj.(sub{:}).hasSubSubOptions + for subsub = obj.(sub{:}).possibleSubOptions + if ~strcmp(obj.(sub{:}).(subsub{:}).optionChosen,otherObj.(sub{:}).(subsub{:}).optionChosen); + logicalOut = false; + if obj.optionLevel == 1 + diffs = [diffs {obj.(sub{:}).optionName}]; %#ok<AGROW> + else + diffs = [diffs {obj.optionName}]; %#ok<AGROW> + end + end + end + else + if ~strcmp(obj.(sub{:}).optionChosen,otherObj.(sub{:}).optionChosen); + logicalOut = false; + if obj.optionLevel == 1 + diffs = [diffs {obj.(sub{:}).optionName}]; %#ok<AGROW> + else + diffs = [diffs {obj.optionName}]; %#ok<AGROW> + end + end + end + end + else + logicalOut = strcmp(obj.optionChosen,otherObj.optionChosen); + end + catch + warning('Unsimilar BearImpOptions objects were compared') + logicalOut = false; + end + diffs = unique(diffs); + end + + function possibleSubOptions = get.possibleSubOptions (obj) + if obj.optionLevel == 1 + possibleSubOptions = fieldnames(BearImpOptions.Possible)'; + elseif obj.optionLevel == 2 + if isstruct(BearImpOptions.Possible.(char(obj.optionName))) + possibleSubOptions = fieldnames(BearImpOptions.Possible.(char(obj.optionName)))'; + elseif iscell(BearImpOptions.Possible.(char(obj.optionName))) + possibleSubOptions = BearImpOptions.Possible.(char(obj.optionName)); + end + elseif obj.optionLevel == 3 + if obj.hasSubSubOptions + possibleSubOptions = fieldnames(BearImpOptions.Possible.(obj.parent.optionName))'; + else + possibleSubOptions = BearImpOptions.Possible.(obj.parent.optionName).(obj.optionName); + end + elseif isstruct(BearImpOptions.Possible.(obj.parent.optionName)) && ismember(obj.optionName,fieldnames(BearImpOptions.Possible.(obj.parent.optionName))) + + else + possibleSubOptions = {}; + end + end + + function hasSubSubOptions = get.hasSubSubOptions(obj) + switch obj.optionLevel + case 1 + hasSubSubOptions = true; + case 2 + hasSubSubOptions = isstruct(BearImpOptions.Possible.(obj.optionName)); + case 3 + if ~isstruct(BearImpOptions.Possible.(obj.parent.optionName)) + hasSubSubOptions = false; + else + hasSubSubOptions = isstruct(BearImpOptions.Possible.(obj.parent.optionName).(obj.optionName)); + end + end + end + + function set_optionChosen(obj,subOptionName,optionChoice) + objBefore = obj.copy; + if ischar(optionChoice) || isstring(optionChoice) + assert(~obj.(subOptionName).hasSubSubOptions || strcmp(optionChoice,'default'),[obj.(subOptionName).optionName ' has suboptions. Set suboptions individually or set to ''default''.']) + mustBeMember(optionChoice,[obj.(subOptionName).possibleSubOptions {'default'}]) + if ~obj.(subOptionName).hasSubSubOptions && strcmp(optionChoice,obj.(subOptionName).defaultOption) + optionChoice = 'default'; + end + obj.(subOptionName).optionChosen = optionChoice; + if strcmp(optionChoice,'default') + if obj.(subOptionName).hasSubSubOptions + for sub = obj.(subOptionName).possibleSubOptions + disp(sub{:}) + obj.(subOptionName).(sub{:}).optionChosen = 'default'; + end + end + obj.optionChosen = 'default'; + else + obj.optionChosen = 'custom suboptions'; + if obj.optionLevel == 2 + obj.parent.optionChosen = 'custom suboptions'; + end + end + else + assert(isa(optionChoice,'BearImpOptions'),'Wrong input datatype for setting an option. Use a string, char or BearImpOptions object.') + assert(strcmp(obj.(subOptionName).optionName,optionChoice.optionName),'The name of the BearImpOptions object differs from the one delivered.') + + prop = findprop(obj,subOptionName); + setMethod = prop.SetMethod; % Wired workaround so that the set function does not call itself recursively + prop.SetMethod = []; + obj.(subOptionName) = optionChoice; + prop.SetMethod = setMethod; + end + [isEqual,optionsChanged] = eq(obj,objBefore); + if ~isEqual + obj.optionsLastChanged = optionsChanged; + notify(obj,'optionChanged') + %disp(optionsChanged) + end + end + end + + methods (Access = protected) + function propgrp = getPropertyGroups(obj) + if ~isscalar(obj) + propgrp = getPropertyGroups@matlab.mixin.CustomDisplay(obj); + else + if obj.hasSubSubOptions + for sub = obj.possibleSubOptions + if obj.(sub{:}).hasSubSubOptions + for subsub = obj.(sub{:}).possibleSubOptions + propList.([sub{:} '_' subsub{:}]) = obj.(sub{:}).(subsub{:}).displayText; + end + else + propList.(sub{:}) = obj.(sub{:}).displayText; + end + end + else + propList = struct(obj.optionName,obj.displayText); + end + propgrp = matlab.mixin.util.PropertyGroup(propList); + end + end + function outText = displayText(obj) + outText = obj.optionChosen; + if strcmp(outText,'default') && ~obj.hasSubSubOptions + outText = [obj.defaultOption ' (default)']; + end + end + function cp = copyElement(obj) + cp = copyElement@matlab.mixin.Copyable(obj); + if obj.hasSubSubOptions + for sub = obj.possibleSubOptions + prop = findprop(cp,sub{:}); + setMethod = prop.SetMethod; % Wired workaround so that the set function is not called as it calls copy resulting in a recursion + prop.SetMethod = []; + cp.(sub{:}) = obj.(sub{:}).copy; + prop.SetMethod = setMethod; + end + end + end + end +end \ No newline at end of file diff --git a/possibleMethods.m b/possibleMethods.m deleted file mode 100644 index f92daad6ff0cda72758ec925432bc398c5783912..0000000000000000000000000000000000000000 --- a/possibleMethods.m +++ /dev/null @@ -1,112 +0,0 @@ -classdef possibleMethods -% Gibt Auskunft über mögliche Berechnungsmethoden der einzelnen -% Berechnungsabschnitte (T, R, G, B, H, C) und enthält eine Funktion zum -% überprüfen des Methodenstructs - -% pmd Berechnungstool Lagerimpedanz -% Autor: Steffen Puchtler, Julius van der Kuip - - methods (Static) % Diese Klasse enthält ausschließlich statische Methoden, sodass kein Objekt initialisiert werden muss - function s = T - s = {'linear','Vogel'}; - end - function s = R - s = {}; - end - function s = G - s = {}; - end - function s = B - s = {'static','dynamic'}; - end - function s = H - s = {'Hamrock/Dowson','Hamrock/Dowson_withoutThermCorr','Moes'}; - end - function s = C - s.unloadedRE = { 'neglect','stateOfTheArt', 'Leander_Parallel','Leander_Radial','LeanderSteffen','TobiasSteffen_Kugelfläche','TobiasSteffen_Laufbahnfläche','semianalytisch3D'}; - s.outsideArea = {'k-factor','neglect','stateOfTheArt','Schneider_k_c','Schneider_k_vh','Leander_Parallel','Leander_Radial','LeanderSteffen','TobiasSteffen_Kugelfläche','TobiasSteffen_Laufbahnfläche','semianalytisch3D'}; - end - - function s = Default - % Gibt ein Rechenmethoden-Struct mit den Default-Methoden aus - s.T = 'Vogel'; - s.B = 'dynamic'; - s.H = 'Hamrock/Dowson'; - s.C.unloadedRE = 'semianalytisch3D'; - s.C.outsideArea = 'semianalytisch3D'; - end - - function method = addDefault(method) - % Ergänzt ein unvollständiges Rechenmethoden-Struct mit den - % Default-Werten - arguments - method (1,1) struct - end - defaultMethod = possibleMethods.Default; - for ii = fields(defaultMethod)' - if ~isfield(method,ii{1}) % Falls Feld ii nicht besetzt, - method.(ii{1}) = defaultMethod.(ii{1}); % überschreibe mit default - elseif isstruct(defaultMethod.(ii{1})) % falls zweite Ebene existiert - for jj = fields(defaultMethod.(ii{1}))' - if ~isfield(method.(ii{1}),jj{1}) % Falls Feld ii in jj nicht besetzt - method.(ii{1}).(jj{1}) = defaultMethod.(ii{1}).(jj{1}); - end - end - end - end - end - - function success = check(method,throwError) - % prüft, ob das Struct method ausschließlich valide Feld- und Methodennamen enthält - % optional: throwError = true gibt error-Meldungen aus - arguments - method (1,1) struct - throwError (1,1) logical = false - end - success = true; - for ii = fields(method)' - if ~any(strcmp(ii,methods(possibleMethods)')) % Prüft Feldname in erster Ebene - success = false; - if throwError - error(['%s ist kein gültiger Feldname im Methoden-Struct\n',... - 'Möglich an dieser Stelle: %s'],... - ii{1}, strjoin(methods(possibleMethods)') ) - end - break - end - if isstruct(method.(ii{1})) % falls zweite Ebene existiert - for jj = fields(method.(ii{1}))' - if ~any(strcmp(jj,fields(possibleMethods.(ii{1}))')) % Prüft Feldname in zweiter Ebene - success = false; - if throwError - error(['%s is kein gültiger Feldname für den Berechnungsabschnitt %s\n',... - 'Möglich an dieser Stelle: %s'],... - jj{1},ii{1},strjoin(fields(possibleMethods.(ii{1}))') ) - end - break - end - if ~any(strcmp(method.(ii{1}).(jj{1}),possibleMethods.(ii{1}).(jj{1}))) % Prüft Methodenname in zweiter Ebene - success = false; - if throwError - error(['%s ist kein gültiger Methodenname zur Berechnung von %s im Berechnungsabschnitt %s\n',... - 'Möglich an dieser Stelle: %s'],... - method.(ii{1}).(jj{1}), jj{1}, ii{1}, strjoin(possibleMethods.(ii{1}).(jj{1})) ) - end - break - end - end - else - if ~any(strcmp(method.(ii{1}),possibleMethods.(ii{1}))) % Prüft Methodenname in erster Ebene - success = false; - if throwError - error(['%s ist kein gültiger Methodenname für den Berechnungsabschnitt %s\n',... - 'Möglich an dieser Stelle: %s'],... - method.(ii{1}), ii{1}, strjoin(possibleMethods.(ii{1})) ) - end - break - end - end - end - end - end -end \ No newline at end of file