Code covered by the BSD License  

Highlights from
Bond graph add-on block library BG V.2.1

image thumbnail
from Bond graph add-on block library BG V.2.1 by Gert-Helge Geitner
Block library enables the graphical programming of Bond Graphs using standard Simulink and editor.

BGV2_KNK
function BGV2_KNK
%Erweiterungsbibliothek Bondgraph V.2 // KN - Element: Konnektoreinstellung
%Setzen der Konnektor-Rckverbindungen fr einen Node-Block

FT00='BGV2_KNK';
FT01='Inconsistent fed power ports - ConnectorSearch / SumInputs';
FT02='Inconsistent consumed power ports: ConnectorSearch / SumOutputs';
FT03='Inconsistent basic block type code - backward search';
FT04='Inconsistent basic block type code - forward search';
FT05='Unsolved ambiguous forward connection:';
FT06='Invalid code for node-element detected';

BG_Ver='BG_V20';                            %Bib-Version: HIER NDERUNGEN VORNEHMEN
s1=[BG_Ver '/BG_KN'];                       %Vergleichsstring Node-Block als Ancestor
handle={gcb};                               %Mit {} !!! - eig. BlockHandle ermitteln
NH=gcb;                                     %Merker fr jeweiligen NodeBlock
x_str=get_param([gcb '/S'],'Inputs');       %Ohne {} !!! - Summe: '+/-' String
FieldNames=fieldnames(get_param(NH,'Dialogparameters')); % Alte NodeBlockVersion ?
if   sum(strcmp(FieldNames(:),'BI')), BI_str=get_param(NH,'BI'); %Schon BI vorhanden?
else                                  BI_str='off'; end %indirekt, da sowieso String
%Danach kein "gcb" mehr! 1. Aufruf bezieht sich sonst auf Bib - wegen load_system
%------------------------------------------------------------------------------------
if isempty(who('global',['X__' BG_Ver]))    %Ist BondgraphBib geschlossen? (BT laden)
   load_system(BG_Ver); end                 %Bib unsichtbar ffnen; fr Zeilen: 41/95
z=length(x_str);                            %Gesamt-Eingangs-Anzahl des Summenblocks
ZU=length(findstr(x_str,'+'));              %ZU-Port-Anzahl
AB=z-ZU;                                    %AB-Port-Anzahl
if strcmp(BI_str,'on') ZU=ZU-1; AB=AB+1; end %Korrektur bei bidirektionalem "-" (KNU)
blks=find_system(NH,'FollowLinks','on','LookUnderMasks','all',...
                   'BlockType','Constant','Name','Dummy');%Sonderfall Durchschleifen?
if ~isempty(blks) AB=AB-1; end              %Korrektur fr "-": Dummy vorhanden!
NH_K=str2num(get_param([NH '/K'],'Value')); %Node: Type (0 oder 1) fr PortNamen

%*************** Zugefhrte Leistung *******************************************
R=0;                                        %Rckwrtssuche
if     NH_K==60|NH_K==63, NH_N='F';         % 0-Node (UM='off') oder 1-Node(UM='on')?
elseif NH_K==61|NH_K==62, NH_N='E';         % 1-Node (UM='off') oder 0-Node(UM='on')?
else   errordlg([NH 10 10 FT06],FT00); end

[vh,vbh]=BGV2_TSI(handle,R);                %Verndert h; vh="Verzweigungs"-Handle
j=length(vh);                               %Wieviele "Verbindungen" gefunden?
if ZU~=j errordlg([NH 10 10 FT01],FT00); end %Keine bereinstimmung fr zugef. Leistg
for j=1:ZU
    h=vh(j); bh=vbh;                        %    >>>AW's von auen<<<
    M1=1;                                   %Merker: zweite while-Bed. nur 1x nutzen
    while ~isstr(bh)|...                    %bh kein String, also HandleNr. oder 0 ?
          (strcmp(get_param(bh,'Ancestorblock'),s1)&M1)|... %s1=Node-Block: 1.mal?
          isempty(findstr(get_param(bh,'Ancestorblock'),BG_Ver)) %Subsysteme/ni.BGE.?
          if isstr(bh) M1=0; end            %2.mal: ist nun aus eigener Maske heraus!
          [h,bh]=BGV2_TSI(h,R);             %Verndert h // rckwrts genau 1 Quelle!
    end
    BT=str2num(get_param([get_param(bh,'Ancestorblock') '/K'],'Value')); %K aus Bib
    K=KonSet(NH,j,NH_N,NH_K,bh,R);  %K aus Anw. // je Konnektor laden / Syntax prfen
    if ~(fix(BT/10)-fix(K/10)==0) errordlg([FT03 10 '(' NH '):' 10 10 bh],FT00); end
end
%*************** Energiespeicher UND Abgefhrte Leistung ***********************
R=1;                                        %Vorwrtssuche
if     NH_K==60|NH_K==62, NH_S='E';         % 0-Node mit UM='off' oder UM='on' ?
elseif NH_K==61|NH_K==63, NH_S='F';         % 1-Node mit UM='off' oder UM='on' ?
else   errordlg([NH 10 10 FT06],FT00); end

[vh,vbh]=BGV2_TSI(handle,R);                %Verndert h; vh="Verzweigungs"-Handle
j=length(vh);                               %Wieviele "Verbindungen" gefunden?
if   strcmp(get_param(NH,'UM'),'off'), Q=1; %Standard Knoteneingang o. Umwandlung?
else                                   Q=0; end    
if (AB+Q)~=j errordlg([NH 10 10 FT02],FT00); end%Keine bereinstmg. fr zugef. Leistg
for j=1:(AB+Q)
    h=vh(j); bh=vbh;                        %    >>>AW's von auen<<<
    M1=1;                                   %Merker1: zweite while-Bed. nur 1x nutzen
    M2=1;                                   %Merker2: Ergebnis mehrdeutig
    h_SP=0;                                 %HandleSpeicher fr Mehdeutigkeiten
    while (~isstr(bh)|...                   %bh kein String, also HandleNr. oder 0 ?
          (strcmp(get_param(bh,'Ancestorblock'),s1)&M1)|... %s1=Node-Block: 1.mal?
          isempty(findstr(get_param(bh,'Ancestorblock'),BG_Ver)))&... %Subsysteme ?
          M2                                %M2 Verzweigung (vorwrts) erkannt ?
          if isstr(bh) M1=0; end            %zweite while-Bedingung ausschalten
          [h,bh]=BGV2_TSI(h,R);             %Verndert h // vorwrts ist mehrdeutig !
          h_L=length(h);                    %Mehrdeutigkeit eingetreten (Verzweiggn)?
          %++++++++++++++ BEGINN: Vorwrtsverzweigung +++++++++++++++++++++++++++++++
          if  h_L>1 
              h_SP=h; M2=0;           %Abbruch ueres while sichern
              M3=1;                   %Abbruch mittleres while sichern
              while ~isempty(h_SP)|M3
                h={h_SP{1}};             %h aus h_SP laden
                h_SP=h_SP(2:end);        %h_SP um diesen Handle krzen
                M4=1;                    %Abbruch inneres while: Pfad ohne BG Block!
                M5=1;                    %wie M1: zweite while-Bed. nur 1x nutzen
                while  (~isstr(bh)|...
                       (strcmp(get_param(bh,'Ancestorblock'),s1)&M5)|...%s1=NB:1.mal?
                       isempty(findstr(get_param(bh,'Ancestorblock'),BG_Ver)))&...
                       M4
                       if isstr(bh) M5=0; end  %zweite while-Bedingung ausschalten
                       [h,bh]=BGV2_TSI(h,R);
                       if isempty(h) M4=0; end %Abbruch inneres while / Pfad ohne BGE
                       h_L=length(h);          %erneut Mehrdeutigkeit(Verzweigungen)?
                       if  h_L>1 h_SP={h_SP{1:end},h{2:end}}; end %zus. in HandleSpei
                end                            %Abbruch wenn ein BG_Element gefunden
                if  M4 & ~isempty(findstr(get_param(bh,'Ancestorblock'),BG_Ver))
                    M3=0;                      %Abbruch mittleres while
                end
              end
              if isempty(h_SP)&M3 errordlg([FT05 10 10 NH 10 'jv=' num2str(j)],FT00);
              end
          end
          %++++++++++++++ ENDE: Vorwrtsverzweigung +++++++++++++++++++++++++++++++++
    end
    if   j==1&NH_K<62, NHnr=0;         %Energiespeicher UND UM=='off'(Kode=60/61)?
         if NH_K==60 NH_N='F'; else NH_N='E'; end %Fr Energiespeicher umgekehrt
    else NH_N=NH_S;                    %Namen fr abgefhrte Energie vorbereitet 
         if   NH_K>61 NHnr=j+ZU;       %UM=='on' (Kode=62/63) --> kein E0/F0
         else         NHnr=j+ZU-1; end %UM=='off'(Kode=60/61)
    end
    
    BT=str2num(get_param([get_param(bh,'Ancestorblock') '/K'],'Value')); %K aus Bib
    K=KonSet(NH,NHnr,NH_N,NH_K,bh,R,h);%K aus Anw. // je Konnektor lad. / Syntax pr.
    if ~(fix(BT/10)-fix(K/10)==0) errordlg([FT04 10 '(' NH '):' 10 10 bh],FT00); end
end
%********* Portreihenfolge liefert SIMULINK ber Funktion BGV2_TSI richtig **********

function K=KonSet(NH,NHnr,NH_N,NH_K,bh,R,h)
%Verbindung gefunden, Konnektor setzen

FT10='BGV2_KNK/KonSet';
FT11='Found invalid backward RG element';
FT12='Found invalid backward ICS element';
FT13='BlockType Code mismatch';
FT14='Found invalid backward RF element';
FT15='Found invalid backward AB element (activated bond)';

K=str2num(get_param([bh '/K'],'Value'));
t=fix(K/10);                                  %Hier nur Typ nicht Einstellg., wie BCN
Pnr=num2str(NHnr);
switch t
  case {1,2,9}                                 % SD / RG / AB
       if     R==0&t==2 errordlg([NH 10 10 FT11],FT10); return %rckwrts RG unzul.
       elseif R==0&t==9 errordlg([NH 10 10 FT15],FT10); return %rckwrts AB unzul.
       end
       Syntax(NH,NH_N,Pnr,NH_K,bh,R);
       if R==1                                 % alle Flle vorwrts
            KN=get_param([bh '/I'],'GotoTag');     %von Vorgnger Konnektor laden
            set_param([NH '/K' Pnr],'GotoTag',KN); %in NodeBlock eintragen:Node <- El
       else                                    %SD rckwrts; Kode ab 070405
            KN=get_param([NH '/K' Pnr],'GotoTag'); %KN von Node auslesen
            set_param([bh '/I'],'GotoTag',KN); %KN: SD <--- Node
       end
  case {3}                                     % ICS
       if R==0 errordlg([NH 10 10 FT12],FT10); %rckwrts IC Element unzulssig
          return; end
       Tag=get_param(bh,'AttributesFormatString');%Merkerabfrage:'E' oder 'F' setzen?
                                    %wenn gesetzt, dann existiert ein Input-Block 'E'
       if isempty(Tag) Name='E'; else Name='F'; end %Hier Alt. KonnektorBlockName lad
       Syntax(NH,NH_N,Pnr,NH_K,bh,R);
       KN=get_param([bh '/' Name],'GotoTag');  %von Vorgnger Konnektor laden
       set_param([NH '/K' Pnr],'GotoTag',KN);  %in NodeBlock eintragen
  case {4,5}                                   % TF / GY
       Syntax(NH,NH_N,Pnr,NH_K,bh,R);
       if ~R                                   %R=0 --> rckwrts
          %ALTER_Kode vor 070405: KN=get_param([bh '/I2'],'GotoTag'); %"rechter" Kon.
          KN=get_param([NH '/K' Pnr],'GotoTag'); %KN von Node auslesen
          set_param([bh '/I2'],'GotoTag',KN);  %"rechter" Konnektor; KN: TG <--- Node
       else                                    %R=1 --> vorwrts
          KN=get_param([bh '/I1'],'GotoTag');  %"linker" Konnektor
          set_param([NH '/K' Pnr],'GotoTag',KN); %                   KN: Node <--- TG
       end
  case {6}                                     % KN
       if R                                    %Vorwrtssuche!; rckwrts ignorieren
          [h,bhw]=BGV2_TSI(h,R); [h,bhw]=BGV2_TSI(h,R); %Vern. h / Inport+Nr finden
          I=findstr(bhw,'/');
          bhw(I(end)+1)='K';                     %aus "E" bzw. "F" ein "K" machen
          Syntax(NH,NH_N,Pnr,NH_K,bh,R);
          KN=get_param(bhw,'GotoTag');           %von Nachfolger Konnektor laden
          set_param([NH '/K' Pnr],'GotoTag',KN); %in NodeBlock eintragen
       end
  case {7}                                           % RF
       if R==0 errordlg([NH 10 10 FT14],FT10);       %rckwrts RF Element unzulssig
          return; end
       [h,bhw]=BGV2_TSI(h,R); [h,bhw]=BGV2_TSI(h,R); %Vern. h / Inport+Nr finden
       I=findstr(bhw,'/');                           %Pfad zum jeweiligen Inport
       PNZ=bhw(I(end)+1);                            %Zwischenspeicher fr "E" / "F"
       bhw(I(end)+1)='I';                            %aus "E" bzw. "F" ein "I" machen
       KR=str2num(get_param([bh '/KR'],'Value'));    %Nur "F" oder "E" ---> KR==0
       if KR~=0                                      %Mixed causal ? KR == 1. E-Nr
          if PNZ=='F', K='76';                       %Mixed nur 2 Ports: "F" -> Nr=1
          else         K='78';                       %wenn nicht "F" dann "E" und
                       bhw(I(end)+2)='2';            %PortNr=2 noch setzen
          end                                        % F1 bzw. E1 ---> I1 bzw. I2 !!
          set_param([bh '/K'],'Value',K);            %Syntax erhlt aktuellen Kode
          K=str2double(K);                           %KonSet Rckgabewert K ist Zahl
       end
       Syntax(NH,NH_N,Pnr,NH_K,bh,R);
       KN=get_param(bhw,'GotoTag');                  %von Nachfolger Konnektor laden
       set_param([NH '/K' Pnr],'GotoTag',KN);        %in NodeBlock eintragen
  case {8}                                           % ICF
       if R==0 errordlg([NH 10 10 FT14],FT10);       %rckwrts ICF Element unzulssig
          return; end
       [h,bhw]=BGV2_TSI(h,R); [h,bhw]=BGV2_TSI(h,R); %Vern. h / Inport+Nr finden
       I=findstr(bhw,'/');                           %Pfad zum jeweiligen Inport
       PNZ=bhw(I(end)+1);                            %Zwischenspeicher fr "E" / "F"
       bhw(I(end)+1)='I';                            %aus "E" bzw. "F" ein "I" machen
       KR=str2num(get_param([bh '/KR'],'Value'));    %Nur "F" oder "E" ---> KR==0
       if KR~=0                                      %Mixed causal ? KR == 1. E-Nr
          K=get_param([bh '/K'],'Value');
          if   PNZ=='F' if K=='86', K='88'; elseif K=='89', K='87'; end  %IF/CF-F
          else          if K=='88', K='86'; elseif K=='87', K='89'; end, %IF/CF-E
                        bhw(I(end)+2)='2';           %wenn E: PortNr=2 noch setzen
          end
          set_param([bh '/K'],'Value',K);            %Syntax erhlt aktuellen Kode
          K=str2double(K);                           %KonSet Rckgabewert K ist Zahl
       end
       Syntax(NH,NH_N,Pnr,NH_K,bh,R);
       KN=get_param(bhw,'GotoTag');                  %von Nachfolger Konnektor laden
       set_param([NH '/K' Pnr],'GotoTag',KN);        %in NodeBlock eintragen
  otherwise errordlg([NH 10 10 FT13],FT10);
end

function Syntax(NH,NH_N,Pnr,NH_K,bh,R)
%SyntaxPrfung E/E bzw. F/F fr alle BG-Verbindungen ausgehend von einem NodeBlock
%NH_K (ist schon Zahl) :   Kode des "Ausgangspunktes" (NodeBlock 0:60 / 1:61)
%NH_N (Namenstring):       Name des I/O-Ports, also "E" oder "F" (NodeBlock)
%Pnr (String):             Nummer des I/O-Ports (NodeBlock; mindestens 0 und 1)
%NH bzw. bh (String=Pfad): Zugriffspfade der jeweiligen Verbindung

FT20='BGV2_KNK/Syntax';
FT21='Syntax case search code mismatch';
FT22=['Syntax error:: "E/F-mismatch" for following connection detected:'];
FT22a='Please reduce node structure:: ';
FT23=[FT22a '"Disabled linkage E/E" for following connection detected:'];
FT24=[FT22a '"Disabled linkage F/F" for following connection detected:'];

if NH_N=='E' ef=58; else ef=60; end      %String --> Zahl (E(69):58 / F(70):60
ZK=str2num(get_param([bh '/K'],'Value'));%Kode des "Zieles"(Zahl) == bel. BG-Element 

if NH_K>61 UM=1; else UM=0; end          %alternativer oder normaler Knoten ?
if ~UM|UM&R                              %Normaler Kn. od. alternativer Kn. vorwrts
    if Pnr~='0', pnr=4; else pnr=0; end      %so kontinuierlicher SwitchBereich
    if NH_K>61,  NH_K=NH_K-2; end            %Node-Grundtyp bei UM=='on' einstellen
    t=NH_K-ef+pnr;                           %so Bereich 0 bis 7 mit Fehlern: 1 und 2
else                                     %Alternativer Knoten rckwrts
    if Pnr~='1', pnr=4; else pnr=0; end      %so kontinuierlicher SwitchBereich
    t=NH_K-ef+6+pnr;                         %so Bereich 8 bis 15; nur: 9 und 10 i.O.
end
%{NH_K, NH_N+0, str2num(Pnr), ZK, NH, bh, t}    %      >>>AnalyseWerkzeug<<<
                                         %ACHTUNG: Node ignoriert RckwrtsPfade !!!
                                         %         vgl. KonSet ---> case 6
switch t
    case{0}                              %K0/F0
        switch ZK
            case {31,35,32,36,82,88,81,87,20,21,70,76,16,17,50,51,40,41,63},
            case {60}, errordlg([FT24 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%FF
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{3}                              %K1/E0
        switch ZK
            case {30,34,33,37,80,86,83,89,22,23,72,78,14,15,52,53,42,43,62},
            case {61}, errordlg([FT23 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EE
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{4}                              %K0/Fx
        switch ZK
            case {12,13,40,41,52,53}
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{5}                              %K1/Fy
        switch ZK
            case {16,17,20,21,31,35,32,36,40,41,50,51,60,70,76,82,88,81,87,90,63},
           %case {63}, errordlg([FT24 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%FF
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{6}                              %K0/Ey
        switch ZK
            case {14,15,22,23,30,34,33,37,42,43,52,53,61,72,78,80,86,83,89,91,62},
           %case {62}, errordlg([FT23 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EE
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{7}                              %K1/Ex
        switch ZK
            case {10,11,42,43,50,51}
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{9}                              %K1/F1, alternativ (rckwrts)
        switch ZK
            case {12,13,40,41,52,53}     %Sicherheisfkt [60/61:kein Eintrag nowendig]
                                         %Ausnahme: Alternativ-Node-Rckwrtssuche
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end
    case{10}                             %K0/E1, alternativ (rckwrts)
        switch ZK
            case {10,11,42,43,50,51}     %Sicherheisfkt [61/60:kein Eintrag nowendig]
                                         %Ausnahme: Alternativ-Node-Rckwrtssuche 
            otherwise  errordlg([FT22 10 10 bh '  <--->  ' NH '/' NH_N Pnr],FT20);%EF
        end  
    otherwise errordlg([NH 10 10 FT21],FT20);
end

Contact us at files@mathworks.com