Search code examples
arraysmodelica

modelica: modifying array parameter in array of components


Hello I want to be able to make the following modification:

Zone.ZONE[nZones] MultiZone(
    nMONOL={{nMONOL[i] for i in (1:nSURFS[j])} for j in 1:nZones});

with nZones = 2

with nSURFS = {2,4}

with nMONOL = {5,4,6,7,8,9}

.

The result should be:

MultiZone[1].nMONOL[2] = {5,4}

MultiZone[2].nMONOL[3] = {6,7,8,9}

But the modification above does not work. Is there a way to make it work? Kind Regards K


Solution

  • Here are two possible solutions that may be sufficient for your purposes. As described by the syntax of your question there is a package Zone which contains a model ZONE. The example model is then what was presented in your question.

    Approach #1

    A couple notes

    • fixed=false allows the definition of nMONOL in an initial algorithm/equation section

    • sum(nSURFS[1:i-1]) is generic to the number of nSURFS specified.

    • Instead of specifing nZones you could have that be dependent on nSURFS. Depends on what is actually occuring with your code though if that makes sense.

      i.e., parameter Integer nZones = size(nSURFS,1)

    The code is as follows:

    package Zone
    
      model ZONE
    
        parameter Integer nSURFS = 2;
        parameter Integer nMONOL[nSURFS](fixed=false); // Notice the modification
    
      end ZONE;
    
      model example
    
        parameter Integer nZones=2;
        parameter Integer nSURFS[nZones]={2,4};
        parameter Integer nMONOL[sum(nSURFS)]={5,4,6,7,8,9};
    
        Zone.ZONE[nZones] MultiZone(nSURFS=nSURFS);
    
      initial algorithm // or initial equation 
    
        for i in 1:nZones loop
          for j in 1:nSURFS[i] loop
            MultiZone[i].nMONOL[j] := nMONOL[j + sum(nSURFS[1:i-1])];
          end for;
        end for;
    
      end example;
    
    end Zone;
    

    Producing the desired result:

    MultiZone[1].nMONOL[2] = {5,4}

    MultiZone[2].nMONOL[4] = {6,7,8,9}

    Approach #2

    Talked with a friend to get inspired for an alternative approach.

    This second approach is an attempt get around the language restriction that type arrays have the same length (at least when you are trying to define them inline). To do so, rely on a matrix where 0 or some other value that makes sense pads the matrix. Internal to the model you can then have a internal (_int) parameter to help clarify what you are using. But that is not necessary so long as you ensure any loops, etc. are keyed to go from 1:nSURFS (i.e., the 0 values will never be used.

    Also the note about nZones in Approach #1 still applies if desired.

    package Zone
      model ZONE
    
        parameter Integer nSURFS = integer(if Modelica.Math.Vectors.find(0,nMONOL) == 0 then size(nMONOL,1) else Modelica.Math.Vectors.find(0,nMONOL)-1);
        parameter Integer nMONOL[:];
        final parameter Integer nMONOL_int[nSURFS] = {nMONOL[i] for i in 1:nSURFS};
    
      end ZONE;
    
      model example
    
        parameter Integer nZones=2;
        parameter Integer nMONOL[nZones,:]={{5,4,0,0},{6,7,8,9}};
    
        Zone.ZONE[nZones] MultiZone(nMONOL = nMONOL);
    
      end example;
    end Zone;
    

    Producing the desired result:

    MultiZone[1].nMONOL[4] = {5,4,0,0}

    MultiZone[1].nMONOL_int[2] = {5,4}

    MultiZone[2].nMONOL[4] = {6,7,8,9}

    MultiZone[2].nMONOL_int[4] = {6,7,8,9}

    Approach #3

    A slightly simpler version of Approach #2. Note, be sure that when using nMONOL in a ZONE type that you loop over nSURFS, or create an internal variable so as to not use the 0 values.

    package Zone
      model ZONE
    
        parameter Integer nSURFS;
        parameter Integer nMONOL[:];
    
      end ZONE;
    
      model example
    
        parameter Integer nZones=2;
        parameter Integer nSURFS[:] = {2, 4};
        parameter Integer nMONOL[nZones,max(nSURFS)]={{5,4,0,0},{6,7,8,9}};
    
        Zone.ZONE[nZones] MultiZone(nSURFS = nSURFS, nMONOL = nMONOL);
    
      end example;
    end Zone;