No corresponding inner declaration found for (Modelica inner/outer) - modeling

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).

Related

Can you use the built in derivative functions in compute shaders? (vulkan)

I want to use the built in derivative funcitons:
vec3 dpdx = dFdx(p);
vec3 dpdy = dFdy(p);
Inside a compute shader. However I get the following error:
Message ID name: UNASSIGNED-CoreValidation-Shader-InconsistentSpirv
Message: Validation Error: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object 0: handle = 0x5654380d4dd8, name = Logical device: GeForce GT 1030, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6bbb14 | SPIR-V module not valid: OpEntryPoint Entry Point <id> '5[%main]'s callgraph contains function <id> 46[%BiplanarMapping_s21_vf3_vf3_f1_], which cannot be used with the current execution modes:
Derivative instructions require DerivativeGroupQuadsNV or DerivativeGroupLinearNV execution mode for GLCompute execution model: DPdx
Derivative instructions require DerivativeGroupQuadsNV or DerivativeGroupLinearNV execution mode for GLCompute execution model: DPdy
%BiplanarMapping_s21_vf3_vf3_f1_ = OpFunction %v4float None %41
Severity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
I don't seem to find anything on the topic when I search online.
Derivative functions only work in a fragment shader. The derivatives are based on the rate-of-change of the value across the primitive being rendered. Obviously compute shaders don't render primitives, so there is nothing to compute.
Apparently, NVIDIA has an extension that provides some derivative computation capabilities for compute shaders. That's where the weird error comes from.
Derivatives in fragment shaders are computed by subtracting between the same value from adjacent invocations. As such, you can emulate this by using shared variables.
First, you have to make sure that the spatially adjacent invocations are in the same work group. So your work group size needs to be some multiple of 2x2 invocations. Then, you need a shared variable array, which you index by invocations within a work group. Each invocation should write its own value to its own index.
To compute the derivative, issue a barrier (with memoryBarrierShared) after writing the values to the shared variables. Take the difference between one's invocation and the adjacent one in the same 2x2 quad. You should make sure that all invocations in the same quad get the same value, by always subtracting between the lower index and the higher index within the quad. Something like this:
uvec2 quadIndex = gl_LocalInvocationID.xy / 2
/*type*/ derFdX = variable[quadIndex.x + 1][quadIndex.y + 0] - variable[quadIndex.x + 0][quadIndex.y + 0]
/*type*/ derFdY = variable[quadIndex.x + 0][quadIndex.y + 1] - variable[quadIndex.x + 0][quadIndex.y + 0]
The NVIDIA extension basically does this for you, though it's probably more efficient since it wouldn't need the shared variable.

Achieving a tunable parameter in OpenModelica

I have the following Modelica code
model RocketCar
Real x;
Real v;
input Real u(min = -1, max = 1);
parameter Real h;
equation
der(x) = h*v;
der(v) = h*u;
end RocketCar;
meant to model the infamous rocket car problem, which I would like to transform into an FMU.
I transform the file using OMShell:
>>> loadFile("RocketCar.mo")
true
>> translateModelFMU(RocketCar)
"/path/to/RocketCar.fmu"
The resulting FMU lists the variable as
<ScalarVariable
name="h"
valueReference="10"
variability="fixed"
causality="parameter"
initial="exact">
<Real start="0.0"/>
</ScalarVariable>
i.e., as a fixed parameter. I would like to change the Modelica code to obtain a tunable parameter in the resulting FMU.
Note that a similar question has been asked and answered already. The suggested solution was to add annotation (Evaluate=false) to the definition of the parameter. However, this answer seems to be specific to Dymola. The suggested annotation seems to have no effect regarding the resulting FMU. Is there an OpenModelica variant of the annotation to achieve the same effect?

Discretizing PDE in space for use with modelica

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;

SSAS calculate a measure result related to two other measures

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;

SystemModeler Connector Weight

I'm looking for "where to start" - I expect that this problem is a bit involved for this forum, but I need a start point, and my search has not been successful as of yet :( any input would be appreciated...
I need to create a Weighted Graph using the SystemModeler / OpenModelica interface. The first step of our process will skip the SystemModeler simulation and pass the model to Mathematica for processing
My question is about adding attributes to a connector in the System Modeler GUI:
I need to draw a model such that: State A is connected to State B and State C, with a weight of .7 for the path to B and .3 the path for C. I need to create an object to hold the weight and associate it with the connector. Also need to warn when connectors from a given state do not add to 1.
Any ideas on where to start ?
As connections in Modelica themselves does not hold any information, rather passing along information from the blocks that it connects, I believe you have two options:
Put a component between two nodes that specifies the weight of the connection.
Have a defined input and output from each node where the output from a node specifies the weight of the connection, and the inputs on a node are summed to check that they equal 1.
Here is an example of how you could do the latter:
model WeightedGraph
model Node
Modelica.Blocks.Interfaces.RealInput u[nin];
Modelica.Blocks.Interfaces.RealOutput y[size(k, 1)];
Real usum;
parameter Real k[:] = {0};
parameter Integer nin = 0;
equation
y = k;
usum = sum(u);
end Node;
Node A(nin = 0, k = {0.7});
Node B(nin = 1, k = {0.3});
Node C(nin = 1);
equation
connect(A.y[1], B.u[1]);
connect(B.y[1], C.u[1]);
end WeightedGraph;
The number of inputs into your component need to be specified using the nin parameter. The number outputs will be equal to the length of k, which is a list where you specify a weight of each connection. You could for example check that ysum adds to 1 using assert or if you wanted to do that in Mathematica.

Resources