I actually need to define a calculated measure showing different results when using / or not a specific dimension.
Ex. Measure1=5, Measure2=8 and by default calculated measure = 5 but if Dim1 is used then calculated measure = 8
I tried with scope but I don't reach the expected result
CREATE MEMBER CURRENTCUBE.[Measures].[MeasureFinal]
As [Measures].[Measure1],
VISIBLE = 1;
SCOPE ([Measures].[MeasureFinal]);
Scope [Dim1].[Location].[Location].members;
This =([Measures].[[Measure2]);
End Scope;
End Scope;
thanks for your help
I think you can do this by using the ALL member of Dim1. ALL is the current member if you're not slicing by Dim1 at all. You'd have to reverse the order of your logic, making your measure 8 unless we're on the Dim1.All member (i.e. Dim1 is not being used):
CREATE MEMBER CURRENTCUBE.[Measures].[MeasureFinal]
As 8,
VISIBLE = 1;
SCOPE ([Measures].[MeasureFinal]);
Scope [Dim1].[Location].[Location].All;
This =(5);
End Scope;
End Scope;
Related
I am currently doing a course called "Modeling of dynamic systems" and have been given the task of modeling a warm water tank in modelica with a distributed temperature description.
Most of the tasks have gone well, and my group is left with the task of introducing the heat flux due to buoyancy effects into the model. Here is where we get stuck.
the equation given is this:
Given PDE
But how do we discretize this into something we can use in modelica?
The discretized version we ended up with was this:
(Qd_pp_b[k+1] - Qd_pp_b[k]) / h_dz = -K_b *(T[k+1] - 2 * T[k] + T[k-1]) / h_dz^2
where Qd_pp_b is the left-hand side variable, ie the heat flux, k is the current slice of the tank and T is the temperature in the slices.
Are we on the right path? or completely wrong?
This doesn't seem to be a differential equation (as is) so this does not make sense without surrounding problem. For the second derivative you should always create auxiliary variables and for each partial derivative a separate equation. I added dummy values for parameters and dummy equations for T[k]. This can be simulated, is this about what you expected?
model test
constant Integer n = 10;
Real[n] Qd_pp_b;
Real[n] dT;
Real[n] T;
parameter Real K_b = 1;
equation
for k in 1:n loop
der(Qd_pp_b[k]) = -K_b *der(dT[k]);
der(T[k]) = dT[k];
T[k] = sin(time+k);
end for;
end test;
In a transport problem, I'm trying to insert the following rule into the objective function:
If a supply of BC <19,000 tons, then we will have a penalty of $ 125 / MT
I added a constraint to check the condition but would like to apply the penalty in the objective function.
I was able to do this in Excel Solver, but the values do not match. I've already checked both, and debugged the code, but I could not figure out what's wrong.
Here is the constraint:
def bc_rule(model):
return sum(model.x[supplier, market] for supplier in model.suppliers \
for market in model.markets \
if 'BC' in supplier) >= 19000
model.bc_rules = Constraint(rule=bc_rule, doc='Minimum production')
The problem is in the objective rule:
def objective_rule(model):
PENALTY_THRESHOLD = 19000
PENALTY_COST = 125
cost = sum(model.costs[supplier, market] * model.x[supplier, market] for supplier in model.suppliers for market in model.markets)
# what is the problem here?
bc = sum(model.x[supplier, market] for supplier in model.suppliers \
for market in model.markets \
if 'BC' in supplier)
if bc < PENALTY_THRESHOLD:
cost += (PENALTY_THRESHOLD - bc) * PENALTY_COST
return cost
model.objective = Objective(rule=objective_rule, sense=minimize, doc='Define objective function')
I'm getting a much lower value than found in Excel Solver.
Your condition (if) depends on a variable in your model.
Normally, ifs should never be used in a mathematical model, and that is not only for Pyomo. Even in Excel, if statements in formulas are simply converted to scalar value before optimization, so I would be very careful when saying that it is the real optimal value.
The good news is that if statements are easily converted into mathematical constraints.
For that, you need to add a binary variable (0/1) to your model. It will take the value of 1 if bc <= PENALTY_TRESHOLD. Let's call this variable y, and is defined as model.y = Var(domain=Binary).
You will add model.y * PENALTY_COST as a term of your objective function to include the penalty cost.
Then, for the constraint, add the following piece of code:
def y_big_M(model):
bigM = 10000 # Should be a big number, big enough that it will be bigger than any number in your
# model, but small enough that it will stay around the same order of magnitude. Avoid
# utterly big number like 1e12 and + if you don't need to, since having numbers too
# large causes problems.
PENALTY_TRESHOLD = 19000
return PENALTY_TRESHOLD - sum(
model.x[supplier, market]
for supplier in model.suppliers
for market in model.markets
if 'BC' in supplier
) <= model.y * bigM
model.y_big_M = Constraint(rule=y_big_M)
The previous constraint ensures that y will take a value greater than 0 (i.e. 1) when the sum that calculates bc is smaller than the PENALTY_TRESHOLD. Any value of this difference that is greater than 0 will force the model to put 1 in the value of variable y, since if y=1, the right hand side of the constraint will be 1 * bigM, which is a very big number, big enough that bc will always be smaller than bigM.
Please, also check your Excel model to see if your if statements really works during the solver computations. Last time I checked, Excel solver do not convert if statements into bigM constraints. The modeling technique I showed you works for absolutely all programming method, even in Excel.
I have recently started using Modelica (OpenModelica) as a modeling tool and I am facing a problem regarding the use of inner/outer functionalities. I am trying to create an environment model containing values for ambient temperature and pressure, so that other models can use this values. I have tried to do so with inner and outer keywords but I keep receiving the following warning:
No corresponding 'inner' declaration found for component .Real
component.T0 declared as 'outer '. The existing 'inner' components
are: .Real ambient.T0; defined in scope: Test.Ambient. Check if
you have not misspelled the 'outer' component name. Please declare
an 'inner' component with the same name in the top scope. Continuing
flattening by only considering the 'outer' component declaration.
Below these lines you can see a simplification of the code I am trying.
The three models below these lines are contained in a package named Test.
The model for ambient in which a temperature T0 is defined as inner:
within Test;
model Ambient
inner Real T0;
equation
T0 = 300;
end Ambient;
The model of a component that tries to call T0 via outer operator:
within Test;
model Component
Real T;
outer Real T0;
parameter Real k = 2;
equation
T = k * time + T0;
end Component;
Both models ambient and component are dragged and dropped in the combined model:
within Test;
model System
Test.Ambient ambient annotation(
Placement(visible = true, transformation(origin = {-30, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Test.Component component annotation(
Placement(visible = true, transformation(origin = {30, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
equation
end System;
When running System I get the aforementioned warning. Also, there is one variable more than equations (which makes sense since it is not being able to connect Component.T0 with Ambient T0)
Your use-case seems pretty similar to what is done in Modelica.Mechanics.MultiBody and Modelica.Fluid. In both cases, there is a class that contains all the "global" properties of the system, called world or system respectively.
Therefore your class Ambient should defined to be an inner class. This is then accessed by an outer statement to re-use values from it. What would be possible when using your code, is to access T0 from models within Ambient. Judging from your example code this is not what you want...
Applying the technique used in the MSL to your example, would result in the following code:
package Test
model Ambient
inner Real T0;
equation
T0 = 300;
annotation(defaultComponentPrefixes="inner");
end Ambient;
model Component
Real T;
Real T0 = ambient.T0;
parameter Real k = 2;
protected
outer Test.Ambient ambient;
equation
T = k * time + T0;
end Component;
model System
inner Test.Ambient ambient;
Test.Component component;
end System;
end Test;
Some comments:
Accessing the variables with the outer statement is done in the protected part of the model, just to prevent to have the same variables multiple times in the result.
The defaultComponentPrefixes annotation ensures, that the model has the prefix inner in case a graphical instance is created (as it is shown in the model System).
I'm trying to port a minizinc model in choco. I know how to define variables and other basic stuff but despite having read the tutorial and some code examples I've some trouble defining some non trivial constraints.
Could someone give me some advice how to translate the following code (just z) in a choco solver style?
array[1..n,1..n] of int: c;
array[1..n] of var 0..10: next;
var 0..sum(c): z = sum(i in 1..n)(c[i,next[i]]);
Thanks!
I believe you know how to post a sum constraint so the non trivial part lies in the c[i,next[i]] which retrieves the integer in matrix c at row i and column next[i]. The problem is that next[i] is a variable so you cannot use it directly to access a (Java) array.
You need to use the element constraint (that is also in minizinc):
/**
* Creates an element constraint: value = table[index]
*
* #param value an integer variable taking its value in table
* #param table an array of integer values
* #param index an integer variable representing the value of value in table
*/
default Constraint element(IntVar value, int[] table, IntVar index)
As you work with a matrix, you need to do that for each row and then post a sum on them.
Note also that in Java, array cells are accessed from 0 to n-1 (in minizinc it is from 1 to n), so you may need to update the model accordingly or use an offset.
Hope this helps
https://www.cosling.com/
I am new to Modelica, and I am wondering if it is possible to write a kind of dynamic programming equation. Assume time is discretized by an integer i, and in my specific application x is boolean and f is a boolean function of x.
x(t_i) = f(x(t_{i+d}))
Where d can be a positive or negative integer. Of course, I would initialize x accordingly, either true or false.
Any help or references would be greatly appreciated!
It is possible. In Modelica the discretization in time is usually carried on by the compiler, you have to take care of the equations (continous dynamics). Otherwise, if you want to generate events at discrete time points, you can do it using when statements.
I suggest you to take a look at Introduction to Object-Oriented Modeling and Simulation with OpenModelica (PDF format, 6.6 MB) - a more recent tutorial (2012) by Peter Fritzson. There is a section that on Discrete Events and Hybrid Systems, that should clarify how to implement your equations in Modelica.
Below you can find an example from that tutorial about the model of a bouncing ball, as you can see discretization in time is not considered when you write your dynamic equations. So the continous model of the ball v=der(s), a=der(v) and than the discrete part inside the when clause that handles the contact with the ground:
model BouncingBall "the bouncing ball model"
parameter Real g=9.81; //gravitational acc.
parameter Real c=0.90; //elasticity constant
Real height(start=10),velocity(start=0);
equation
der(height) = velocity;
der(velocity)=-g;
when height<0 then
reinit(velocity, -c*velocity);
end when;
end BouncingBall;
Hope this helps,
Marco
If I understand your question, you want to use the last n evaluations of x to determine the next value of x. If so, this code shows how to do this:
model BooleanHistory
parameter Integer n=10 "How many points to keep";
parameter Modelica.SIunits.Time dt=1e-3;
protected
Boolean x[n];
function f
input Integer n;
input Boolean past[n-1];
output Boolean next;
algorithm
next :=not past[1]; // Example
end f;
initial equation
x = {false for i in 1:n};
equation
when sample(0,dt) then
x[2:n] = pre(x[1:(n-1)]);
x[1] = f(n, x[2:n]);
end when;
end BooleanHistory;