AnyLogic: Need some help about SD modular and engine accuracy - anylogic

Please have a look at my model first:
Plane moving model
It's a simple model describe a plane at [40,20,20] move to [60,40,40].
The meaning of my SD modular is :
“x_fromFunc, y_fromFunc, z_fromFunc”: the exact value of agent position get from "this.getX()" function, the unit is meter;
"vx, vy, vx": the speed along x, y, z axis calculated by the equation "(x_fromFunc-delay(x_fromFunc,dt))/dt", where dt=2;
"x_fromSD, y_fromSD, z_fromSD": the calculated agent position using stocks custom equation "d(x_fromSD)/dt=vx";
"engineTimeStep": equels to "getEngine().getNextStepTime()-time()";
"d_fromFunc": "this.distanceTo(40, 20, 20)";
"v": "this.getSpeed()";
"d_fromSD": "d(d_fromSD)/dt=v".
When I run the model:
before consider engineTimeStep
I read some answers in SOF(Thanks to "Felipe"'s answers) and I know the "x_fromSD, y_fromSD, z_fromSD" update at the dynamic time step "engineTimeStep" which is controlled by the continuous engine. But I don't understand why its value is wrong in this case, especially since the value of "d_fromFunc" is right. So I change the stocks custom equation to "d(x_fromSD)/dt=vx*engineTimeStep". Then the running result turns out to be:
after consider engineTimeStep
"x_fromSD, y_fromSD, z_fromSD" don't have same value as “x_fromFunc, y_fromFunc, z_fromFunc”. Why this phenomenon occurs? How to make different equation like "(x_fromFunc-delay(x_fromFunc,dt))/dt" more precise? Or is there any method to calculate precise "vx, vy, vz" and their integral in Anylogic?

Related

Inversing the modelica simulation model: steady state model

I want to know if a model can be inversed in modelica. (here inverse means: if in causal statement y= x +a; x and a are input and y is output; but if I want to find 'x' as output and 'y' and 'a' as input, the model is called reversed/inversed model) For example, if I have compressor with input air port and output air port, and port has variables associated with it are pressure(P), temperature(T) and mass flow rate(mdot). I have simple steady state model containing three equations as follow:
OutPort.mdot = InPort.mdot
OutPort.P = rc * InPort.P
OutPort.T = InPort.T * (1 + rc[ (gamma-1)/gamma) - 1][/sup] / eta);
Here, rc, gamma and eta are compression ratio, ratio of specific heat capacitites and efficiency of compressor respectively.
I want to know, if I know values of : gamma, eta, OutPort.mdot, OutPort.P and OutPort.T and InPort.P and InPort.T, can I find the value of rc.
Can I find values of rc and how should be the model of compressor with above equation in Modelica. As far as I know, there are some variables designated as parameters which can not be changed during simulation. How the modelica model should be with above equations
Thanks
Yes, this should not be a problem as long as you make sure that rc is not a parameter, but a normal variable, and you supply the appropriate number of known quantities to achieve a balanced system (roughly, number of unknowns matches number of equations).
E.g. in your case if you know/supply OutPort.P and InPort.P, rc is already determined from eq 2. Then, in the third equation, there are no unknowns left, so either the temperature values are consistent with the equation or you (preferably) leave one temperature value undetermined.
In addition if you only want to compute the parameter rc during steady-state initialization i.e. that nothing changes with time that is also possible:
...
parameter Real rc(fixed=false);
initial equation
Inport.mdot=12; // Or something else indirectly determining rc.
The fixed=false means that rc is indirectly determined from the initialization. However, if the model is not completely stationary it will only find the correct rc during the initialization and then use that afterwards.

How to calculate a variable using two different sets of equations selected according a criteria from large data set in Matlab

I have to calculate a variable (settling velocity ) using two different sets of equations selected according a criteria from large data set using Matlab.
I load all sediment diameter (D50) values in a text file. Then I have to calculate settling velocity.
Settling velocity depends on the sediment diameter. For sand I want to use one set of equations and for silt and clay I want another set of equations. The criteria is D50 > 0.0000625.
I used if and else conditions (please see the script written by me; I am new to matlab, this may not be efficient).
However, it uses only one set of equations to calculate settling velocity. There should be a problem of writing if condition. Here is the sample data set.
D50=
0.0002626
0.0002626
0.000003504
0.0000108
0.0000985
The answer I get;
ws=
0.069
0.069
0.0000123
0.000117
0.009717
But the answer should be;
ws=
0.03681
0.03681
0.0000123
0.000117
0.009717
According to the results from following scripts, I can see that the calculations were done only using the equations after else condition. The calculations under if condition were not done. I have done calculations using only one set of equations separately. I get the write answers.
But I want to include two set of equations and do the calculations according to criteria defined here. (This calculation is only a part of large script to simulate morphological evolution due to sea-level rise for my PhD work. Previously my script included only the first set of equation but I want to improve the model using two set of equations.)
Below is my code. I am very grateful to anyone who can help me to sort out this problem.
%%% Settling velocity
g=9.81;
psed=2650;
pw=1027;
neu=0.000001004;
p=0.4;
load D50.txt
i=1:length(D50);
if D50(i) > 0.0000625
Dstar=D50(i)*(g*((psed/pw)-1)/neu^2)^(1/3);
Dstarpower=Dstar.^3;
j=1:length(Dstarpower);
idleA=ones(size(D50));
idleB=107.3296*idleA+1.049*Dstarpower;
idleC=idleB.^0.5;
idleD=idleC-10.36*idleA;
idleE=neu*idleD;
ws=idleE./D50
else
ws=1000000*(D50.^2)
end
CoefA=ws/((1-p)*psed);
fileID1=fopen('ws.txt','w');
fprintf(fileID1,'%6.6f\r\n',ws);
fclose(fileID1);
fileID2=fopen('CoefA.txt','w');
fprintf(fileID2,'%6.6f\r\n',CoefA);
fclose(fileID2);

Simulating spatial PDEs in Modelica - Accessing variable values at specific times

This question is somewhat related to a previous question of mine, where I didn't quite get the right solution. Link: Earlier SO-thread
I am solving PDEs which are time variant with one spatial dimension (e.g. the heat equation - see link below). I'm using the numerical method of lines, i.e. discretizing the spatial derivatives yielding a system of ODEs which are readily solved in Modelica (using the Dymola tool). My problems arise when I simulate the system, or when I plot the results, to be precise. The equations themselves appear to be solved correctly, but I want to express the spatial changes in all the discretized state variables at specific points in time rather than the individual time-varying behavior of each discrete state.
The strategy leading up to my problems is illustrated in this Youtube tutorial, which by the way is not made by me. As you can see at the very end of the tutorial, the time-varying behavior of the temperature is plotted for all the discrete points in the rod, individually. What I would like is a plot showing the temperature through the rod at a specific time, that is the temperature as a function of the spatial coordinate. My strategy to achieve this, which I'm struggling with, is: Given a state vector of N entries:
Real[N] T "Temperature";
..I would use the plotArray Dymola function as shown below.
plotArray( {i for i in 1:N}, {T[i] for i in 1:N} )
Intuitively, this would yield a plot showing the temperature as a function of the spatial coordiate, or the number in the line of discrete units, to be precise. Although this command yields a result, all T-values appear to be 0 in the plot, which is definitely not the case. My question is: How can I successfully obtain and plot the temperatures at all the discrete points at a given time? Thanks in advance for your help.
The code for the problem is as indicated below.
model conduction
parameter Real rho = 1;
parameter Real Cp = 1;
parameter Real L = 1;
parameter Real k = 1;
parameter Real Tlo = 0;
parameter Real Thi = 100;
parameter Real Tinit = 30;
parameter Integer N = 10 "Number of discrete segments";
Real T[N-1] "Temperatures";
Real deltaX = L/N;
initial equation
for i in 1:N-1 loop
T[i] = Tinit;
end for;
equation
rho*Cp*der(T[1]) = k*( T[2] - 2*T[1] + Thi) /deltaX^2;
rho*Cp*der(T[N-1]) = k*( Tlo - 2*T[N-1] + T[N-2]) /deltaX^2;
for i in 2:N-2 loop
rho*Cp*der(T[i]) = k*( T[i+1] - 2*T[i] + T[i-1]) /deltaX^2;
end for
annotation (uses(Modelica(version="3.2")));
end conduction;
Additional edit: The simulations show clearly that for example T[3], that is the temperature of discrete segment no. 3, starts out from 30 and ends up at 70 degrees. When I write T[3] in my command window, however, I get T3 = 0.0 in return. Why is that? This is at the heart of the problem, because the plotArray function would be working if I managed to extract the actual variable values at specific times and not just 0.0.
Suggested solution: This is a rather tedious solution to achieve what I want, and I hope someone knows a better solution. When I run the simulation in Dymola, the software generates a .mat-file containing the values of the variables throughout the time of the simulation. I am able to load this file into MATLAB and manually extract the variables of my choice for plotting. For the problem above, I wrote the following command:
plot( [1:9]' , data_2(2:2:18 , 10)' )
This command will plot the temperatures (as the temperatures are stored together with their derivates in the data_2 array in the .mat-file) against the respetive number of the discrete segment/element. I was really hoping to do this inside Dymola, that is avoid using MATLAB for this. For this specific problem, the amount of variables was low on account of the simplicity of this problem, but I can easily image a .mat-file which is signifanctly harder to navigate through manually like I just did.
Although you do not mention it explicitly I assume that you enter your plotArray command in Dymola's command window. That won't work directly, since the variables you see there do not include your simulation results: If I simulate your model, and then enter T[:] in Dymola's command window, then the printed result is
T[:]
= {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}
I'm not a Dymola expert, and the only solution I've found (to actively store and load the desired simulation results) is quite cumbersome:
simulateModel("conduction", resultFile="conduction.mat")
n = readTrajectorySize("conduction.mat")
X = readTrajectory("conduction.mat", {"Time"}, n)
Y = readTrajectory("conduction.mat", {"T[1]", "T[2]", "T[3]"}, n)
plotArrays(X[1, :], transpose(Y))

Modelica - Modeling a slider element in OpenModelica

Rheological models are usually build using three (or four) basics elements, which are :
The spring (existing in Modelica.Mechanics.Translational.Components for example). Its equation is f = c * (s_rel - s_rel0);
The damper (dashpot) (also existing in Modelica.Mechanics.Translational.Components). Its equation is f = d * v_rel; for a linear damper, an could be easily modified to model a non-linear damper : f = d * v_rel^(1/n);
The slider, not existing (as far as I know) in this library... It's equation is abs(f)<= flim. Unfortunately, I don't really understand how I could write the corresponding Modelica model...
I think this model should extend Modelica.Mechanics.Translational.Interfaces.PartialCompliant, but the problem is that f (the force measured between flange_b and flange_a) should be modified only when it's greater than flim...
If the slider extends PartialCompliant, it means that it already follows the equations flange_b.f = f; and flange_a.f = -f;
Adding the equation f = if abs(f)>flim then sign(f)*flim else f; gives me an error "An independent subset of the model has imbalanced number of equations and variables", which I couldn't really explain, even if I understand that if abs(f)<=flim, the equation f = f is useless...
Actually, the slider element doesn't generate a new force (just like the spring does, depending on its strain, or just like the damper does, depending on its strain rate). The force is an input for the slider element, which is sometime modified (when this force becomes greater than the limit allowed by the element). That's why I don't really understand if I should define this force as an input or an output....
If you have any suggestion, I would greatly appreciate it ! Thanks
After the first two comments, I decided to add a picture that, I hope, will help you to understand the behaviour I'm trying to model.
On the left, you can see the four elements used to develop rheological models :
a : the spring
b : the linear damper (dashpot)
c : the non-linear damper
d : the slider
On the right, you can see the behaviour I'm trying to reproduce : a and b are two associations with springs and c and d are respectively the expected stress / strain curves. I'm trying to model the same behaviour, except that I'm thinking in terms of force and not stress. As i said in the comment to Marco's answer, the curve a reminds me the behaviour of a diode :
if the force applied to the component is less than the sliding limit, there is no relative displacement between the two flanges
if the force becomes greater than the sliding limit, the force transmitted by the system equals the limit and there is relative displacement between flanges
I can't be sure, but I suspect what you are really trying to model here is Coulomb friction (i.e. a constant force that always opposes the direction of motion). If so, there is already a component in the Modelica Standard Library, called MassWithStopAndFriction, that models that (and several other flavors of friction). The wrinkle is that it is bundled with inertia.
If you don't want the inertia effect it might be possible to set the inertia to zero. I suspect that could cause a singularity. One way you might be able to avoid the singularity is to "evaluate" the parameter (at least that is what it is called in Dymola when you set the Evaluate flat to be true in the command line). No promises whether that will work since it is model and tool dependent whether such a simplification can be properly handled.
If Coulomb friction is what you want and you really don't want inertia and the approach above doesn't work, let me know and I think I can create a simple model that will work (so long as you don't have inertia).
A few considerations:
- The force is not an input and neither an output, but it is just a relation that you add into the component in order to define how the force will be propagated between the two translational flanges of the component. When you deal with acausal connectors I think it is better to think about the degrees of freedom of your component instead of inputs and outputs. In this case you have two connectors and independently at which one of the two frames you will recieve informations about the force, the equation you implement will define how that information will be propagated to the other frame.
- I tested this:
model slider
extends
Modelica.Mechanics.Translational.Interfaces.PartialCompliantWithRelativeStates;
parameter Real flim = 1;
equation
f = if abs(f)>flim then sign(f)*flim else f;
end slider;
on Dymola and it works. It is correct modelica code so it should be work also in OpenModelica, I can't think of a reason why it should be seen as an unbalance mathematical model.
I hope this helps,
Marco

Modelica: use of der() in a custom class/model

I'm trying to learn Modelica and I have constructed a very simple model using the multibody library. the model consists of a world object and a body (mass) connected to to beams which are then connected to 2 extended PartialOneFrame_a classes (see below) which I modified to create a constant force in one axis. essentially all this group of objects does is fall under gravity and spin around due to the two forces acting at a longituidnal offset from the body center creating a couple about the cg.
model Constant_Force
extends Modelica.Mechanics.MultiBody.Interfaces.PartialOneFrame_a;
parameter Real force = 1.0;
equation
frame_a.f = {0.0,0.0,force};
frame_a.t = {0.0,0.0,0.0};
end Constant_Force;
I next wanted see if I could create a very simple aerodynamic force component which I would connect to the end of one the rotating 'arms'. My idea was to follow the example of the Constant_force model above and for my first simple cut generate forces based on the local frame velocities. This where my problem arose - I tried to compute the velocity using der(frame_a.r_0) which I was then going to transform to local frame using resolve2 function but adding the der(...) line caused the model to not work properly - it would 'successfully' simulate (using OpenModelica) but the v11b vector (see below) would be all zeros, so would der(frame_a.r_0) that appeared for plot plotting - not only that, all the other component behaviors were now also just zero constantly - (frame_a.r_0, w_a etc of the body).
model Aerosurf
extends Modelica.Mechanics.MultiBody.Interfaces.PartialOneFrame_a;
import Modelica.Mechanics.MultiBody.Frames;
import Modelica.SIunits;
//Real[3] v11b;
SIunits.Velocity v11b[3];
//initial equation
// v11b={0.0,0.0,0.0};
algorithm
//v11b:=der(frame_a.r_0);
equation
v11b=der(frame_a.r_0);
frame_a.f = {0.0,0.0,0.0};
frame_a.t = {0.0,0.0,0.0};
end Aerosurf;
I tried a number of ways just to simply compute the velocities (you will see from the commented lines) so i could plot to check correct behavior but to no avail. I used algorithm or equation approach - I did acheive some different (but also incorrect behaviours) with the different approaches.
Any tips? I must be missing something fundamental here, it seems the frame component does not inherently carry the velocity vector so I must have to compute it??
The simplest way is to use the Modelica.Mechanics.MultiBody.Sensors.AbsoluteVelocity block from MSL and connect it to your MB frame, then just use the variable of the output connector in your equation.