Modelica - Is it possible to set name of a submodel as the value of another variable? - modelica

I’m quite noob in Modelica language and I’d appreciate any help about this simple issue. I’d like to know if it’s possible to write variables name (that depends on a submodel) as a function of other variable in order to shorten the general code. Here there is an example about what I’d like to do.
I’m considering a top-level model that includes three identical submodels (OpenTank) of the Standard Modelica Library (tank1,tank2 and tank3). I’d like to know if it’s possible to call the variable (“level”) inside the submodels from the top-level model using a loop like this way (example code is attached) or something similar instead of repeating the code three times (I’m really interested in setting this operation in the top-level model)
What would you advise me to do? Thanks in advance!
model threeTanks
Modelica.Fluid.Vessels.OpenTank tank1;
Modelica.Fluid.Vessels.OpenTank tank2;
Modelica.Fluid.Vessels.OpenTank tank3;
equation
for i in 1:3 loop
tank(i).level= /* … */;
end for;
end threeTanks;

You would need a component iterator, which is proposed in Modelica Change Proposal MCP-0021 Component Iterators. But it is not available yet and nothing has changed since 2016 if I read it correct, so don't expect to get that soon.
With the current Modelica language version (specified in Modelica Language Specification 3.5), you must use literal names when you refer to components.
(In Modelica, there is nothing like eval which you might know from other languages.)
So either go for Rene Just Nielsens solution and use vectorized tanks.
This works, but in the graphical view you will have only one tank. The parameter window will then accept vectors and the tank connectors will be vectorized as well.
If you don't want that, you can also instantiate your tanks as you did and manually specify the component names over which you want to iterate:
for item in {tank1, tank2, tank3} loop
item.level= /* … */;
end for;
The question is also what you want to achieve. The tank already has equations to compute the level, so it's unlikely that you want to set it.
Maybe you want to gather all levels at top in one variable. You could do that by adding this line:
Modelica.Units.SI.Length levels[3] = {item.level for item in {tank1, tank2, tank3}};

Similar to the answer to the post (Modelica - Is it possible to set name of a variable as the value of another variable?) you can declare an array of components like this:
model threeTanks
Modelica.Fluid.Vessels.OpenTank[3] tank;
equation
for i in 1:3 loop
tank[i].level= /* … */;
end for;
end threeTanks;

Related

How to extract an MSL model, modify the code, and use locally?

I am interested to replace my own PID-regulator models with MSL/Blocks/Continuous/LimPID. The problem is that this model restricts limitations of output signals to be parameters and thus do not allow time-varying limits, which I need to have.
Studying the code I understand that the output limitation is created by a block MSL/Blocks/Nonlinear/Limiter and I just want to change this to the block VariableLimiter.
I can imagine that you need to ensure that changes of output-limitations vary in a time-scale slower than the regulator in order to not excite unwanted behaviour of the controller. Still here is a class of problems where it would be very useful to allow this limits to vary slowly.
Thanks for the good input to my question and below a very simple example to refine my question. (The LimPID is more complicated and I come back to that).
Let us instead just modify the block Add to a local block in MyModel.
I copy the code from Modelica.Blocks.Math.Add and call it Addb in MyModel. Since here is a dependence of Interfaces.SI2SO I need to make an import before the extends-clause. This import I take from the ordinary general MSL package, instead of copying also that in to MyModel. Then I introduce a new parameter "bias" and modify the equation. The annotation may need some update as well but we do not bother with that now.
MyModel
...
block Addb "Output the sum of the two inputs"
import Modelica.Blocks.Interfaces;
extends Interfaces.SI2SO;
parameter Real k1=+1 "Gain of input signal 1";
parameter Real k2=+1 "Gain of input signal 2";
parameter Real bias=0 "Bias term";
equation
y = k1*u1 + k2*u2 + bias;
annotation (...);
end Addb;
MyModel;
This code seems to work.
My added new question is whether it is enough to look up "extends-clauses" and other references to MSL and make the proper imports since the code is now local, or here are more aspects to think of? The LimPID code is rather complex with procedures for initialization etc so I just wonder if here is more to do than just bring in a number of import-clauses?
The models in Modelica Standard Library (MSL) should only be seen as exemplary models, not covering all possible applications. MSL is write protected and it is not possible to replace the limiter block in LimPID (and add max/min input connectors). Also, it wouldn't work out if you shared your simulation model with others, expecting their MSL to work like your modified MSL.
Personally, I have my own libraries of components where MSL models are inadequate. For example, I have PID controllers with variable limits, manual/automatic functions and many more functions which are needed in my applications.
Often, I create a copy of an MSL model, place it in the same package in my own library and make the necessary modifications and additions, e.g. MyLibrary.Blocks.Continuous.PID.

Abaqus HETVAL or DFLUX Input Variables : Possible to create heat flux dependent on stresses and strain rate?

I'm new to abaqus subroutines and Fortran in general and a bit confused right now. I'm trying to simulate the anelastic heat dissipation during cyclic loading. Because of that I need some way to define a heat flux which is dependent on strain, stress and possibly some damge Parameter. There are different user subroutines like HETVAL or DFLUX which seem to be appropriate for this problem, but in the Documentation it states that none of these can use stresses or strains as input variables.
SUBROUTINE HETVAL(CMNAME,TEMP,TIME,DTIME,STATEV,FLUX,
1 PREDEF,DPRED)
C
INCLUDE 'ABA_PARAM.INC'
C
CHARACTER*80 CMNAME
C
DIMENSION TEMP(2),STATEV(*),PREDEF(*),TIME(2),FLUX(2),
1 DPRED(*)
user coding to define FLUX and update STATEV
RETURN
END
SUBROUTINE DFLUX(FLUX,SOL,KSTEP,KINC,TIME,NOEL,NPT,COORDS,
1 JLTYP,TEMP,PRESS,SNAME)
C
INCLUDE 'ABA_PARAM.INC'
C
DIMENSION FLUX(2), TIME(2), COORDS(3),
CHARACTER*80 SNAME
user coding to define FLUX(1) and FLUX(2)
RETURN
END
As you see neither Hetvall nor DFLUX support Stresses 'S' or Strains 'LE' (logarithmic strain) as input variables.
I already googled extensively but could't find anyone withe the same problem. So i just wanted to ask if someone else managed to teach the HETVAL or DFLUX Subroutine to read solution variables like stresses or strains? Is that even possible at all? My Problem actually shouldn't be that hard the biggest problem is to tell abaqus what to do.
Thank you!:)
It looks like you can access 'S' or 'LE' through state variables which are part of the HETVAL subroutine. You can access and modify the state variables in the USDFLD subroutine, which is called before HETVAL. In your USDFLD subroutine you call the GETVRM utility routine to get 'S' or 'LE' and can then set the corresponding state variable to that value.

Global CONSTANTS. Any problem using them?

I've been programming for over 6 years now and i've always avoided using global variables because there is always another way around the problems.
Today, i work on a (big) project, we want to use a dictionnary of mathematical CONSTANTS what will never be modified anywhere. The only problem i seem to find with globals on internet is the fact that if someone overwrites one it could bug out the whole project. But as mine are constants this problem doesnt apply.
(as a second security to avoid people creating a variable with the same name as one of the constants i will probably pack them all in a single global struct)
Does anyone know of problems that still happend using global constants?
Thanks for your answers! :)
In MATLAB, your best bet for mathematical constants is to define a class with properties that have the Constant attribute. This is described in the doc here, and here's the leading example from that page:
classdef NamedConst
properties (Constant)
R = pi/180
D = 1/NamedConst.R
AccCode = '0145968740001110202NPQ'
RN = rand(5)
end
end
This way, the values cannot be overridden. (Note that there's something a little perhaps unexpected in this example - the value of the property RN changes each time the class is loaded! I personally wouldn't write code like that...)
The old-fashioned standard way to create a constant in MATLAB is to write a function. For example pi is a function. It could be written as:
function value = pi
value = 3.14159;
end
Of course we can overwrite the value of pi in MATLAB, but it is always a local change, it is not possible to affect another workspace.

Exploit Matlab copy-on-write by ensuring function arguments are read-only?

Background
I'm planning to create a large number of Matlab table objects once, so that I can quickly refer to their contents repeatedly. My understanding is that each table variable/column is treated in copy-on-write manner. That is, if a table column is not modified by a function, then a new copy is not created.
From what I recall of C++ as of 1.5 decades ago, I could ensure that the code for a function does not modify its argument's data by using constant-correctness formalism.
The specific question
I am not using C++ in these days, but I would like to achieve a similar effect of ensuring that the code for my Matlab function doesn't change the data for selected arguments, either inadvertently or otherwise. Does anyone know of a nonburensome way to do this, or just as importantly, whether this is an unrealistic expectation?
I am using R2015b.
P.S. I've web searched and came across various relevant articles, e.g.:
http://www.mathworks.com/matlabcentral/answers/359410-is-it-possible-to-avoid-copy-on-write-behavior-in-functions-yet
http://blogs.mathworks.com/loren/2007/03/22/in-place-operations-on-data
(which I need clarification on to fully understand, but it isn't my priority just now)
However, I don't believe that I am prematurely optimizing. I know that I don't want to modify the tables. I just need a way to enforce that without having to go through contortions like creating a wrapper class.
I've posted this at:
* Stack Overflow
* Google groups
There is no way of making variables constants in MATLAB, except by creating a class with a constant (and static?) member variable. But even then you can do:
t = const_table_class.table;
t(1,1) = 0; % Created and modified a copy!
The reason that a function does not need to mark its inputs as const is because arguments are always passed by value. So a local modification does not modify data in the caller’s workspace. const is something that just doesn’t exist in the MATLAB language.
On the other hand, you can be certain that your data will not be modified by any of the functions you call. Thus, as long as the function that owns the tables does not modify them, they will remain constant. Any function you pass these tables to, if they attempt to modify them, they will create a local copy to be modified. This is only locally a problem. The memory used up by this copy will be freed upon function exit. It will be a bug in the function, but not affect code outside this function.
You can define a handle class that contains a table as it's preperty. Define a property set listener that triggers and generates error/warning when the value of the property changes.
classdef WarningTable < handle
properties (SetObservable)
t
end
methods
function obj = WarningTable(varargin)
obj.t = table(varargin);
addlistener(obj,'t','PreSet',...
#(a,b)warning('table changed!'));
end
end
end
This should generate warning:
mytable = WarningTable;
mytable.t(1,1) = 0;

Simulink - How to create independent custom blocks using callback functions

I am currently coding a new library with several models in it (I am used to Matlab, but not to Simulink). I am able to create a model with block parameters, let's say parameter 'p', and a callback function (initfct) which uses this parameter to compute specific values used inside my model (let say a simple gain K=K(p)).
My problem is that my parameter 'p' and 'K' are available directly on the workspace, what I don't want to. Moreover, if I use twice or more this model in a system, the two models share always the same 'K', which also I don't want to.
So how I can make these variables 'p' and 'K' independent when I use my custom model several time, and to prevent these variables to be viewed in the workspace ?
Should I use "Reference models", but I am not familiar with this feature ... ?
Thanks for you answer,
Michael
Within a callback, gcb returns the path to the block which currently executes the callback. Having the path, you can use get_param to access the parameters.
Just for demonstation purposes, insert the following to the MoveFcn of a delay block:
set_param(gcb,'DelayLength',num2str(randi(10)))
It will randomly change the delay whenever the block is moved.
I am not sure if my answer explains everything you need. It might be that you also need a Mask. If you think this answer is incomplete, please update your question and include a small example model demonstrating your problem.
Thanks, with your help I was able to solve the problem.
To be more specific if someone else has the same problem : you need in your mask to declare also internal variables used by the callback function. Unchecked the relevant options so that they not appear as standard input parameters of your model.
My problem was also to use num2str instead of mat2str (when the gain was a matrix acting on multiple inputs).