2013-02-03 16 views
6

Sto provando a costruire un modello che avrà equazioni leggermente diverse in base all'esistenza o meno di alcuni componenti (nel mio caso, porte fluide).dichiarazione di componente condizionale e una seguente equazione se

Un codice come il seguente non funziona:

parameter Boolean use_component=false; 
Component component if use_component; 
equation 
if use_component then 
    component.x = 0; 
end if; 

Come posso ovviare a questo?

risposta

8

Se si desidera utilizzare i componenti condizione, ci sono alcune restrizioni è necessario essere a conoscenza. La sezione 4.4.5 della specifica Modelica 3.3 lo riassume bene. Dice "Se la condizione è falsa, il componente, i suoi modificatori e qualsiasi equazione di connessione che coinvolge il componente, vengono rimossi". Ti mostrerò come usarlo per risolvere il tuo problema in un secondo, ma prima voglio spiegare perché la tua soluzione non funziona.

Il problema ha a che fare con il controllo del modello. Nel tuo caso, è ovvio che l'equazione component.x e il componente component esistono entrambi o nessuno dei due esiste. Questo perché li hai legati alla stessa variabile booleana. Ma cosa succede se tu avessi non questo:

parameter Real some_number; 
Component component if some_number*some_number>4.0; 
equation 
if some_number>=-2 and some_number<=2 then 
    component.x = 0; 
end if; 

possiamo vedere che questo logicamente identico al vostro caso. Non esiste alcuna possibilità che lo component.x esista quando lo component è assente. Ma possiamo provare cose del genere in generale? No.

Così, quando sono stati introdotti i componenti condizionali, la semantica conservatori sono stati implementati che possono sempre banalmente garantire che i set di variabili ed equazioni coinvolte non arrivano mai "fuori sincrono".

Cerchiamo di tornare a ciò che la specifica dice: "Se la condizione è falsa, la componente, i suoi modificatori, e qualsiasi equazioni di connessione che coinvolgono la componente, vengono rimossi"

Per il vostro caso, la soluzione potrebbe potenzialmente essere abbastanza semplice. A seconda di come dichiari "x", puoi semplicemente aggiungere una modifica a component, ad es.

parameter Boolean use_component=false; 
Component component(x=0) if use_component; 

L'eleganza di questo è che la modifica si applica solo a component e se component non è presente, né è la modifica (equazione). Quindi la variabile x e la sua equazione associata sono "sincronizzati". Ma questo non funziona per tutti i casi (IIRC, x deve avere un qualificatore input perché funzioni ... forse è possibile nel tuo caso?).

Ci sono due alternative rimanenti. Per prima cosa, metti l'equazione component.x all'interno di component. Il secondo è quello di introdurre un connettore su component che, se connesso, genererà l'equazione desiderata. Come nel caso di modifica (questa non è una coincidenza), si potrebbe associare x con un connettore di ingresso di qualche tipo e poi fare questo:

parameter Boolean use_component; 
Component component if use_component; 
Constant zero(k=0); 
equation 
connect(k.y, component.x); 

Ora, potevo immaginare che dopo aver considerato tutti e tre i casi (modifica, internalizzare l'equazione e utilizzare connect), si arriva alla conclusione che nessuno di essi funzionerà. In questo caso, vorrei suggerire umilmente che hai un problema con il modo in cui hai progettato il componente. Il motivo per cui tali restrizioni si presentano è legato alla necessità di verificare i componenti da soli per la correttezza. Ciò richiede che il componente sia completo ("bilanciato" nella terminologia della specifica).

Se non riesci a risolvere il problema con gli approcci che ho menzionato sopra, allora sospetto che tu abbia davvero un problema di bilanciamento e che tu abbia probabilmente bisogno di ridefinire i confini del tuo componente in qualche modo. Se questo è il caso, ti suggerirei di aprire un'altra domanda qui con i dettagli di ciò che stai cercando di fare.

1

Penso che il motivo per cui questo non funzionerà è che il parser cercherà la dichiarazione della variabile "component.x" che, se il componente non è attivo, non esiste. Non funziona anche se si inserisce "Evaluate = true" nell'annotazione. La soluzione più pulita secondo me è lavorare a livello di equazione e abilitare diversi gruppi di equazioni nello stesso blocco. È possibile creare un modello di wrapper con connettori e parametri corretti, quindi se è un modello causale, ad esempio, è possibile utilizzare classi sostituibili per parametrizzare i modelli come funzioni, oppure, nel caso di modelli acausal, inserire le equazioni all'interno se affermazioni. Un'altra possibile soluzione consiste nel posizionare due modelli diversi all'interno di un blocco, in modo da poter utilizzare le loro variabili nella sezione equazione e quindi creare connessioni condizionali che consentano l'utilizzo del blocco con il comportamento scelto. In altre parole, è possibile creare un "modello di avvolgimento" con due blocchi all'interno, quindi posizionare le equazioni di connessione sui connettori del modello di wrap all'interno delle istruzioni if. Ricordarsi di costruire il modello in modo che ci sia un sistema coerente di quazioni anche per i blocchi non utilizzati. Ma questa non è la soluzione migliore, perché se i blocchi sono grandi dovrai aspettare più tempo per la compilazione poiché tutto verrà compilato.

Spero che questo vi aiuterà,

Marco

0

Si può anche fare un componente fittizio che non è visibile nello strato di grafica:

connector DummyHeatPort 
    "Dummy heatport to facilitate optional heatport. Use this with a conditional heatport by connecting it to the heatport. Then use the -DummyHeatPort.Q_flow in the thermal energy balance." 
    Modelica.SIunits.Temperature T "Port temperature"; 
    flow Modelica.SIunits.HeatFlowRate Q_flow 
    "Heat flow rate (positive if flowing from outside into the component)"; 
end DummyHeatPort; 

Poi, quando questo viene utilizzato in un modello a due porte

Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatport if use_heat_port; 
DummyHeatPort dummy_heatport; 

...

equation 
flowport_a.H_flow + flowport_b.H_flow - dummy_heatport.Q_flow = storage 
    "thermal energy balance"; 
    connect(dummy_heatport, heatport); 

In questo modo lo scali viene utilizzato se presente ma non causa altrimenti un errore.

Problemi correlati