Replacement of deprecated function cardinality(c) in Modelica
Asked Answered
C

4

6

In the documentation it is indicated, that cardinality() function is deprecated and should no longer be used. However, it is still used in the libraries such as ThermoSysPro.

e.g.

if (cardinality(C) == 0) then
 some code
end if;

where C is FluidInlet or FluidOutlet

Could anyone give a simple example of how it could be replaced?

Coleslaw answered 21/11, 2019 at 15:1 Comment(0)
D
7

The usual solution is to make the connector conditional, and if enabled you require that it is connected.

For physical connectors you can see how heatports and support is handled in: Modelica.Electrical.Analog.Interfaces.ConditionalHeatPort Modelica.Mechanics.Rotational.Interfaces.PartialElementaryOneFlangeAndSupport2

For control signals you can see how p_in, h_in etc are handled in Modelica.Fluid.Sources.Boundary_pT Modelica.Fluid.Sources.Boundary_ph

However, the connectors of ThermoSysPro belong in neither of those categories and that should ideally also be cleaned up.

Dunnage answered 22/11, 2019 at 17:9 Comment(0)
C
3

The only thing I know, that could be used in this regard, is the connectorSizing annotation. It is described in the MLS chapter 18.7.

It is used a number of times in the Modelica Standard Library, e.g. in Modelica.Blocks.Math.MinMax via the parameter nu. When using it, the tool automatically sets the modifier for nu according to the number of connections to it.

  parameter Integer nu(min=0) = 0 "Number of input connections"
    annotation (Dialog(connectorSizing=true));
  Modelica.Blocks.Interfaces.RealVectorInput u[nu];

In the example below, nu=2 is generated by Dymola automatically when creating a connection in the graphical layer. I have removed the graphical annotations, to make the code more readable.

model ExCS
  Modelica.Blocks.Math.MinMax minMax(nu=2);
  Modelica.Blocks.Sources.Sine sine(freqHz=6.28);
  Modelica.Blocks.Sources.Constant const(k=0.5);

equation 
  connect(sine.y, minMax.u[1]);
  connect(const.y, minMax.u[2]);
end ExCS;
Crary answered 21/11, 2019 at 15:50 Comment(0)
S
3

The cardinality() operator is used in Modelica.Fluid.Sources.BaseClasses.PartialSource, and in a similar way in other fluid libraries (IBSPA, AixLib, Buildings, BuildingSystems and IDEAS), in the form

  // Only one connection allowed to a port to avoid unwanted ideal mixing
  for i in 1:nPorts loop
    assert(cardinality(ports[i]) <= 1,"
      each ports[i] of boundary shall at most be connected to one component.
      If two or more connections are present, ideal mixing takes
      place with these connections, which is usually not the intention
      of the modeller. Increase nPorts to add an additional port.
     ");
   end for;

I occasionally had models from users who somehow ended up with more than one connection to a ports[i]. How this happened was not clear, but I find the use of cardinality() useful to catch such situations, which otherwise can yield to mixing in the fluid port which the user did not intent and which are hard to detect.

Sophistry answered 23/1, 2020 at 17:27 Comment(2)
I also think that this function is rather useful, but it is depreciated and it will be removed in the future for my understanding. There must be some genuine reasoning behind if the developers decided to remove it. Though it would be interesting to hear it.Coleslaw
..and on the back of that question: what will you be using for that purpose in the future, when cardinality has been removed? It's strange to have a feature deprecated, but no clear successor/alternative named.Jayme
C
0

Based on the answer of Markus A. I produced an example of how to use the connector sizing in order to avoid to use the cardinality with a ThermoSysPro connector.
I deleted the placement annotation part and the code lines with h, h_vol and Q from ThermoSysPro to improve readability.

model Example_pressure_source_sizing_connector_without_cardinality
  parameter Modelica.Units.SI.AbsolutePressure P0=2e5 "Fluid pressure if not connected";
  parameter Integer nPortsP(min=0)=0  "Number of Pressure ports" annotation (Dialog(connectorSizing=true));

  Modelica.Blocks.Interfaces.RealInput InputP[nPortsP];

  ThermoSysPro.WaterSteam.Connectors.FluidInlet C;
equation 

  /* Pression */
  if nPortsP == 0 then /*if there is no connection then use the default pressure defined in parameter*/
   C.P = P0;
  elseif nPortsP == 1 then /* if there is a connection then use the signal of the real input */
   C.P = InputP[1];
  else
    assert(nPortsP<=1, "To many connection to the port", AssertionLevel.error);  /*assert to be sure to have only one connection*/
  end if;

end Example_pressure_source_sizing_connector_without_cardinality;

For me it works pretty well on Dymola 2022, and it avoids me to use a conditional connector with the need to use a boolean parameter (as the example of: Modelica.Electrical.Analog.Interfaces.ConditionalHeatPort etc.)

EDIT : There is a limitation to this approach. For now, on Dymola 2022, It is not working for an Input signal sized as a vector. (and was not working either with cardinality as far as I know). For example : With a connector :

connector Connector_vector
  Modelica.Units.SI.AbsolutePressure P_F[5];
end Connector_vector;

Used within this model :

model Pressure_source_sizing_connector
  parameter Modelica.Units.SI.AbsolutePressure P_F0[5]={30,30,30,30,30} "Fluid pressure if not connected";
  parameter Integer nPortsP(min=0)=0  "Number of Pressure ports" annotation (Dialog(connectorSizing=true));
  parameter Integer vector_size = 5;

  Modelica.Blocks.Interfaces.RealInput InputP[nPortsP*vector_size];
  Connector_vector Connector_vector;
equation 

  /* Pression */
  if nPortsP == 0 then /*if there is no connection then use the default pressure defined in parameter*/
   Connector_vector.P_F = P_F0;
  elseif nPortsP == 1 then /* if there is a connection then use the signal of the real input */
   Connector_vector.P_F = InputP;
  else
    assert(nPortsP<=1, "To many connection to the port", AssertionLevel.error);  /*assert to be sure to have only one connection*/
  end if;
end Pressure_source_sizing_connector;

And connect it to a combitable of the same size :

model Test_connexion
  Pressure_source_sizing_connector example_pressure_source_sizing_connector;
  Modelica.Blocks.Sources.CombiTimeTable combiTimeTable(table=[0.0,0.0,0.0,0.0,0.0,0.0; 1,1,2,3,4,5]);
equation 
  connect(combiTimeTable.y, example_pressure_source_sizing_connector.InputP);
end Test_connexion;

There is not a nPortsP modifier. Nevertheless If I add it manually

model Test_connexion
  Pressure_source_sizing_connector example_pressure_source_sizing_connector(nPortsP=1);
  Modelica.Blocks.Sources.CombiTimeTable combiTimeTable(table=[0.0,0.0,0.0,0.0,0.0,0.0; 1,1,2,3,4,5]);
equation 
  connect(combiTimeTable.y, example_pressure_source_sizing_connector.InputP);
end Test_connexion;

There is no problem. Maybe it will be fixed one day.

Chantay answered 17/7 at 8:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.