f# break function evaluation - time

I have to minimize a quite complicate function. For the minimization I use the NonLinearProgram from the Extreme Optimization Library. Since there´s no way to find a global minimum, I use different startpoints and choose, then the "best minimum". My problem is there can be some startpoints, which evaluatin can take a very long time. Is there some general way in F# or some special method in Extreme Optimization, to stop the evaluation let´s say after 10 min and just give a list with [nan; nan; nan; nan; nan; nan] back?
let funcFindPara (startpoint:float list) func =
let nlp = new NonlinearProgram(6)
// add the function
nlp.ObjectiveFunction <- (fun x -> func x.[0] x.[1] x.[2] x.[3] x.[4] x.[5])
// add lineare constraints
nlp.AddLinearConstraint("a + d > 0", Vector.Create(1.0, 0.0, 0.0, 1.0, 0.0, 0.0), 1.0e-5, infinity) |> ignore
nlp.AddLinearConstraint("c > 0", Vector.Create(0.0, 0.0, 1.0, 0.0, 0.0, 0.0), 1.0e-5, infinity) |> ignore
nlp.AddLinearConstraint("d > 0", Vector.Create(0.0, 0.0, 0.0, 1.0, 0.0, 0.0), 1.0e-5, infinity) |> ignore
nlp.AddLinearConstraint("gamma > 0", Vector.Create(0.0, 0.0, 0.0, 0.0, 1.0, 0.0), 1.0e-5, infinity) |> ignore
nlp.AddLinearConstraint("0 < rho_infty <= 1", Vector.Create(0.0, 0.0, 0.0, 0.0, 0.0, 1.0), 1.0e-5, 1.0) |> ignore
// add nonlinear constrains
// gamma <= -ln(rho_infty)
nlp.AddNonlinearConstraint((fun (x : Vector) -> x.[4] + log(x.[5])), ConstraintType.LessThanOrEqual, 0.0, (fun (x : Vector) -> fun (y : Vector) ->
y.[0] <- 0.0
y.[1] <- 0.0
y.[2] <- 0.0
y.[3] <- 0.0
y.[4] <- 1.0
y.[5] <- 1.0 / x.[5]
y
)
) |> ignore
// add starting point
nlp.InitialGuess <- Vector.Create(startpoint.[0], startpoint.[1], startpoint.[2], startpoint.[3], startpoint.[4], startpoint.[5])
// solve
let solution = nlp.Solve()
// return list with parameters
List.init 6 (fun index -> solution.[index])

You could wrap the function with async { } and pass that to RunSynchronously along with a timeout:
let withTimeout f timeout defaultValue =
try Async.RunSynchronously((async { return f() }), timeout)
with :? System.TimeoutException -> defaultValue
let longFn() =
System.Threading.Thread.Sleep(5000)
[1.0; 2.0; 3.0]
//Usage
withTimeout longFn 2000 [nan; nan; nan]

Related

How to solve a set of ODEs in Scilab?

I have following set of ODEs which I would like to numerically solve in Scilab
I have successfully written the function for evaluating the right hand side of the first equation in other words I am able to solve the first equation
function ut = u(t)
ut = [Vm*cos(2*%pi*fs*t); Vm*sin(2*%pi*fs*t)];
endfunction
function dxdt = SystemModel(t, x, u)
A = [(-RS*(LL + LM)^2 - RR*LM^2)/(LL*LM*(LL + LM)), 0.0, RR/(LL*(LL + LM)), pp*wm/LL;
0.0, (-RS*(LL + LM)^2 - RR*LM^2)/(LL*LM*(LL + LM)), -pp*wm/LL, RR/(LL*(LL + LM));
(LM*RR)/(LL + LM), 0.0, -RR/(LL + LM), -pp*wm;
0.0, (LM*RR)/(LL + LM), pp*wm, -RR/(LL + LM)];
B = [(LL + LM)/(LL*LM), 0.0; 0.0, (LL + LM)/(LL*LM); 0.0, 0.0; 0.0, 0.0];
dxdt = A*x + B*u(t);
endfunction
My problem is that I don't know how to write similar function for evaluation of the right hand side of the second equation because it depends on solution of the first equation. Can anybody give me an advice how to do that?
Possible solution:
x0 = zeros(4, 1);
xtilde0 = zeros(4, 1);
X0 = [x0; xtilde0];
t0 = 0;
dt = 0.001;
t = 0:dt:1;
function ut = u(t)
ut = [Vm*cos(2*%pi*fs*t); Vm*sin(2*%pi*fs*t)];
endfunction
function dXdt = RightHandSide(t, X, u)
x = X(1:4);
xtilde = X(5:8);
// dx/dt = A*x + B*u
A = [(-RS*(LL + LM)^2 - RR*LM^2)/(LL*LM*(LL + LM)), 0.0, RR/(LL*(LL + LM)), pp*wm/LL;
0.0, (-RS*(LL + LM)^2 - RR*LM^2)/(LL*LM*(LL + LM)), -pp*wm/LL, RR/(LL*(LL + LM));
(LM*RR)/(LL + LM), 0.0, -RR/(LL + LM), -pp*wm;
0.0, (LM*RR)/(LL + LM), pp*wm, -RR/(LL + LM)];
B = [(LL + LM)/(LL*LM), 0.0; 0.0, (LL + LM)/(LL*LM); 0.0, 0.0; 0.0, 0.0];
// dxtilde/dt = (An - L*Cn)*xtilde + (dA - L*dC)*x + dB*u
An = [(-RSn*(LLn + LMn)^2 - RRn*LMn^2)/(LLn*LMn*(LLn + LMn)), 0.0, RRn/(LLn*(LLn + LMn)), pp*wm/LLn;
0.0, (-RSn*(LLn + LMn)^2 - RRn*LMn^2)/(LLn*LMn*(LLn + LMn)), -pp*wm/LLn, RRn/(LLn*(LLn + LMn));
(LMn*RRn)/(LLn + LMn), 0.0, -RRn/(LLn + LMn), -pp*wm;
0.0, (LMn*RRn)/(LLn + LMn), pp*wm, -RRn/(LLn + LMn)];
K = 1.5;
l1 = (K - 1.0)*((RSn*(LLn + LMn)^2 + RRn*LMn^2)/(LLn*LMn*(LLn + LMn)) + RRn/(LLn + LMn));
l2 = (K - 1.0)*pp*wm;
l3 = (K^2 - 1.0)*((RSn*(LLn + LMn)^2 + RRn*LMn^2)/(LMn*(LLn + LMn)) - (LMn*RRn)/(LLn + LMn)) - (K - 1)*((RSn*(LLn + LMn)^2 + RRn*LMn^2)/(LMn*(LLn + LMn)) + (LLn*RRn)/(LLn + LMn));
l4 = -(K - 1.0)*LLn*wm*pp;
L = [l1, l2;
-l2, l1;
l3, l4;
-l4, l3];
Bn = [(LLn + LMn)/(LLn*LMn), 0.0; 0.0, (LLn + LMn)/(LLn*LMn); 0.0, 0.0; 0.0, 0.0];
Cn = [1.0, 0.0, 0.0, 0.0; 0.0, 1.0, 0.0, 0.0];
A = [(-RS*(LL + LM)^2 - RR*LM^2)/(LL*LM*(LL + LM)), 0.0, RR/(LL*(LL + LM)), pp*wm/LL;
0.0, (-RS*(LL + LM)^2 - RR*LM^2)/(LL*LM*(LL + LM)), -pp*wm/LL, RR/(LL*(LL + LM));
(LM*RR)/(LL + LM), 0.0, -RR/(LL + LM), -pp*wm;
0.0, (LM*RR)/(LL + LM), pp*wm, -RR/(LL + LM)];
B = [(LL + LM)/(LL*LM), 0.0; 0.0, (LL + LM)/(LL*LM); 0.0, 0.0; 0.0, 0.0];
C = [1.0, 0.0, 0.0, 0.0; 0.0, 1.0, 0.0, 0.0];
dA = An - A;
dB = Bn - B;
dC = Cn - C;
dxdt = A*x + B*u(t);
dxtildedt = (An - L*Cn)*xtilde + (dA - L*dC)*x + dB*u(t);
dXdt = [dxdt; dxtildedt];
endfunction
X = ode(X0, t0, t, list(RightHandSide, u));
Let y = x_tilde. Let assume that it is a 3x1 vector (we can't guess its size with your current presentation).
Build the column X = [x1 x2 x3 x4 y1 y2 y3].' (big X)
Express the column (dX/dt) according to X coordinates and t
Convert the system built in 2) into a Scilab function X_dot = Xder(t, X)
Build the initial state vector Xinit = [x1(t_init); x2(t_init); .. y3(t_init)]
Define the vector t of times to which you want the values of X. They all likely have to be ≥ t_init, and must be strictly increasing.
call X = ode(Xinit, t_init, t, Xder)
X(:,i) should then be the values of X components for each t(i) date.
You can "back-split" big X into x = X(1:4,:) and x_tilde = X(5:$,:).

Why am I seeing these blending artifacts in my GLSL shader?

I'm attempting to create a shader that additively blends colored "blobs" (kind of like particles) on top of one another. This seems like it should be a straightforward task but I'm getting strange "banding"-like artifacts when the blobs blend.
First off, here's the behavior I'm after (replicated using Photoshop layers):
Note that the three color layers are all set to blendmode "Linear Dodge (Add)" which as far as I understand is Photoshop's "additive" blend mode.
If I merge the color layers and leave the resulting layer set to "Normal" blending, I'm then free to change the background color as I please.
Obviously additive blending will not work on top of a non-black background, so in the end I will also want/need the shader to support this pre-merging of colors before finally blending into a background that could have any color. However, I'm content for now to only focus on getting the additive-on-top-of-black blending working correctly, because it's not.
Here's my shader code in its current state.
const int MAX_SHAPES = 10;
vec2 spread = vec2(0.3, 0.3);
vec2 offset = vec2(0.0, 0.0);
float shapeSize = 0.3;
const float s = 1.0;
float shapeColors[MAX_SHAPES * 3] = float[MAX_SHAPES * 3] (
s, 0.0, 0.0,
0.0, s, 0.0,
0.0, 0.0, s,
s, 0.0, 0.0,
s, 0.0, 0.0,
s, 0.0, 0.0,
s, 0.0, 0.0,
s, 0.0, 0.0,
s, 0.0, 0.0,
s, 0.0, 0.0
);
vec2 motionFunction (float i) {
float t = iTime;
return vec2(
(cos(t * 0.31 + i * 3.0) + cos(t * 0.11 + i * 14.0) + cos(t * 0.78 + i * 30.0) + cos(t * 0.55 + i * 10.0)) / 4.0,
(cos(t * 0.13 + i * 33.0) + cos(t * 0.66 + i * 38.0) + cos(t * 0.42 + i * 83.0) + cos(t * 0.9 + i * 29.0)) / 4.0
);
}
float blend (float src, float dst, float alpha) {
return alpha * src + (1.0 - alpha) * dst;
}
void mainImage (out vec4 fragColor, in vec2 fragCoord) {
float aspect = iResolution.x / iResolution.y;
float x = (fragCoord.x / iResolution.x) - 0.5;
float y = (fragCoord.y / iResolution.y) - 0.5;
vec2 pixel = vec2(x, y / aspect);
vec4 totalColor = vec4(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < MAX_SHAPES; i++) {
if (i >= 3) {
break;
}
vec2 shapeCenter = motionFunction(float(i));
shapeCenter *= spread;
shapeCenter += offset;
float dx = shapeCenter.x - pixel.x;
float dy = shapeCenter.y - pixel.y;
float d = sqrt(dx * dx + dy * dy);
float ratio = d / shapeSize;
float intensity = 1.0 - clamp(ratio, 0.0, 1.0);
totalColor.x = totalColor.x + shapeColors[i * 3 + 0] * intensity;
totalColor.y = totalColor.y + shapeColors[i * 3 + 1] * intensity;
totalColor.z = totalColor.z + shapeColors[i * 3 + 2] * intensity;
totalColor.w = totalColor.w + intensity;
}
float alpha = clamp(totalColor.w, 0.0, 1.0);
float background = 0.0;
fragColor = vec4(
blend(totalColor.x, background, alpha),
blend(totalColor.y, background, alpha),
blend(totalColor.z, background, alpha),
1.0
);
}
And here's a ShaderToy version where you can view it live — https://www.shadertoy.com/view/wlf3RM
Or as a video — https://streamable.com/un25t
The visual artifacts should be pretty obvious, but here's a video that points them out: https://streamable.com/kxaps
(I think they are way more prevalent in the video linked before this one, though. The motion really make them pop out.)
Also as a static image for comparison:
Basically, there are "edges" that appear on certain magical thresholds. I have no idea how they got there or how to get rid of them. Your help would be highly appreciated.
The inside lines are where totalColor.w reaches 1 and so alpha is clamped to 1 inside them. The outside ones that you've traced in white are the edges of the circles.
I modified your ShaderToy link by changing float alpha = clamp(totalColor.w, 0.0, 1.0); to float alpha = 1.0; and float intensity = 1.0 - clamp(ratio, 0.0, 1.0); to float intensity = smoothstep(1.0, 0.0, ratio); (to smooth out the edges of the circles) and now it looks like the first picture.

Parallel Computing with Julia #parallel and SharedArray

I have been trying to implement some parallel programming in Julia using #parallel and SharedArrays.
Xi = Array{Float64}([0.0, 450.0, 450.0, 0.0, 0.0, 450.0, 450.0, 0.0])
Yi = Array{Float64}([0.0, 0.0, 600.0, 600.0, 0.0, 0.0, 600.0, 600.0])
Zi = Array{Float64}([0.0, 0.0, 0.0, 0.0, 400.0, 400.0, 400.0, 400.0])
Xj = Array{Float64}([0.0, 450.0, 450.0, 0.0, 0.0, 450.0, 450.0, 0.0])
Yj = Array{Float64}([0.0, 0.0, 600.0, 600.0, 0.0, 0.0, 600.0, 600.0])
Zj = Array{Float64}([0.0, 0.0, 0.0, 0.0, 400.0, 400.0, 400.0, 400.0])
L = Array{Float64}([400.0, 400.0, 400.0, 400.0, 450.0, 600.0, 450.0, 600.0])
Rot = Array{Float64}([90.0, 90.0, 90.0, 90.0, 0.0, 0.0, 0.0, 0.0])
Obviously these vectors will be huge, but for simplicity I just put this limited size.
This is the operation without parallel computing:
function jt_transcoord(Xi, Yi, Zi, Xj, Yj, Zj, Rot, L)
r = Vector(length(Xi))
for i in 1:length(Xi)
rxX = (Xj[i] - Xi[i]) / L[i]
rxY = (Yj[i] - Yi[i]) / L[i]
rxZ = (Zj[i] - Zi[i]) / L[i]
if rxX == 0 && rxY == 0
r[i] = [0 0 rxZ; cosd(Rot[i]) -rxZ*sind(Rot[i]) 0; sind(Rot[i]) rxZ*cosd(Rot[i]) 0]
else
R=sqrt(rxX^2+rxY^2)
r21=(-rxX*rxZ*cosd(Rot[i])+rxY*sind(Rot[i]))/R
r22=(-rxY*rxZ*cosd(Rot[i])-rxX*sind(Rot[i]))/R
r23=R*cosd(Rot[i])
r31=(rxX*rxZ*sind(Rot[i])+rxY*cosd(Rot[i]))/R
r32=(rxY*rxZ*sind(Rot[i])-rxX*cosd(Rot[i]))/R
r33=-R*sind(Rot[i])
r[i] = [rxX rxY rxZ;r21 r22 r23;r31 r32 r33]
end
end
return r
end
The returned value is basically an array that contains a matrix in each vector row. That looks something like this:
r =
[[0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0],
[0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0],
[0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0],
[0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0],
[1.0 0.0 0.0; 0.0 -0.0 1.0; 0.0 -1.0 -0.0],
[0.0 1.0 0.0; 0.0 -0.0 1.0; 1.0 0.0 -0.0],
[-1.0 0.0 0.0; 0.0 0.0 1.0; 0.0 1.0 -0.0],
[0.0 -1.0 0.0; -0.0 0.0 1.0; -1.0 -0.0 -0.0]]
This is my function using #parallel. First of all I need to convert the vectors to SharedArrays:
Xi = convert(SharedArray, Xi)
Yi = convert(SharedArray, Yi)
Zi = convert(SharedArray, Zi)
Xj = convert(SharedArray, Xj)
Yj = convert(SharedArray, Yj)
Zj = convert(SharedArray, Zj)
L = convert(SharedArray, L)
Rot = convert(SharedArray, Rot)
This the same code but using #parallel
function jt_transcoord_parallel(Xi, Yi, Zi, Xj, Yj, Zj, Rot, L)
r = SharedArray{Float64}(zeros((length(Xi),1)))
#parallel for i in 1:length(Xi)
rxX = (Xj[i] - Xi[i]) / L[i]
rxY = (Yj[i] - Yi[i]) / L[i]
rxZ = (Zj[i] - Zi[i]) / L[i]
if rxX == 0 && rxY == 0
r[i] = [0 0 rxZ; cosd(Rot[i]) -rxZ*sind(Rot[i]) 0; sind(Rot[i]) rxZ*cosd(Rot[i]) 0]
else
R=sqrt(rxX^2+rxY^2)
r21=(-rxX*rxZ*cosd(Rot[i])+rxY*sind(Rot[i]))/R
r22=(-rxY*rxZ*cosd(Rot[i])-rxX*sind(Rot[i]))/R
r23=R*cosd(Rot[i])
r31=(rxX*rxZ*sind(Rot[i])+rxY*cosd(Rot[i]))/R
r32=(rxY*rxZ*sind(Rot[i])-rxX*cosd(Rot[i]))/R
r33=-R*sind(Rot[i])
r[i] = [rxX rxY rxZ;r21 r22 r23;r31 r32 r33]
end
end
return r
end
I just got a vector of zeros. My question is: Is there a way to implement this function using #parallel in Julia and get the same results that I got in my original function?
The functions jt_transcoord and jt_transcoord_parallel have major coding flaws.
In jt_transcoord, you are assigning an array to a vector element position. For example, you write r = Vector(length(Xi)) and then assign r[i] = [rxX rxY rxZ;r21 r22 r23;r31 r32 r33]. But r[i] should be a number, and you instead assign it a 3x3 matrix. I suspect that Julia is quietly changing types for you.
SharedArray objects will not admit this lax type conversion behavior. The components of a SharedArray must be of a single primitive type such as Float64, and Vector{Matrix} is not a primitive type. Open a Julia v0.6 REPL and copy/paste the following code:
r = SharedArray{Float64}(length(Xi))
for i in 1:length(Xi)
rxX = (Xj[i] - Xi[i]) / L[i]
rxY = (Yj[i] - Yi[i]) / L[i]
rxZ = (Zj[i] - Zi[i]) / L[i]
if rxX == 0 && rxY == 0
r[i] = [0 0 rxZ; cosd(Rot[i]) -rxZ*sind(Rot[i]) 0; sind(Rot[i]) rxZ*cosd(Rot[i]) 0]
else
R = sqrt(rxX^2+rxY^2)
r21 = (-rxX*rxZ*cosd(Rot[i])+rxY*sind(Rot[i]))/R
r22 = (-rxY*rxZ*cosd(Rot[i])-rxX*sind(Rot[i]))/R
r23 = R*cosd(Rot[i])
r31 = (rxX*rxZ*sind(Rot[i])+rxY*cosd(Rot[i]))/R
r32 = (rxY*rxZ*sind(Rot[i])-rxX*cosd(Rot[i]))/R
r33 = -R*sind(Rot[i])
r[i] = [rxX rxY rxZ;r21 r22 r23;r31 r32 r33]
end
end
On my end, I get:
ERROR: MethodError: Cannot `convert` an object of type Array{Float64,2} to an object of type Float64
This may have arisen from a call to the constructor Float64(...),
since type constructors fall back to convert methods.
Stacktrace:
[1] setindex!(::SharedArray{Float64,2}, ::Array{Float64,2}, ::Int64) at ./sharedarray.jl:483
[2] macro expansion at ./REPL[26]:6 [inlined]
[3] anonymous at ./<missing>:?
Essentially, Julia is telling you that it cannot assign a matrix to a SharedArray vector.
What are your options?
If you insist on having a Vector{Matrix} return type, then use r = Vector{Matrix{Float64}}(length(Xi)) in jt_transcoord. But you cannot use SharedArrays for this since Vector{Matrix} is not an admissible primitive type.
Alternatively, if you are willing to operate with tensors (i.e. 3-way arrays) then you can use pseudocode A below. But SharedArray computing will only help you if you carefully account for which process owns which portion of the tensor. Otherwise, the processes will need to communicate with each other, and your parallelized function could execute very slowly.
If you are willing to lay your 3x3 matrices in a 3n x 3 columnwise fashion, then you can use pseudocode B below.
Pseudocode A
function jt_transcoord_tensor(Xi, Yi, Zi, Xj, Yj, Zj, Rot, L)
# initialize array
r = Array{Float64}(3,3,length(Xi))
# r = SharedArray{Float64,3}((3,3,length(Xi))) # for SharedArrays
for i in 1:length(Xi)
# #parallel for i in 1:length(Xi) # for SharedArrays
# other code...
r[:,:,i] = [0 0 rxZ; cosd(Rot[i]) -rxZ*sind(Rot[i]) 0; sind(Rot[i]) rxZ*cosd(Rot[i]) 0]
# other code...
r[:,:,i] = [rxX rxY rxZ;r21 r22 r23;r31 r32 r33]
end
end
return r
end
Pseudocode B
function jt_transcoord_parallel(Xi, Yi, Zi, Xj, Yj, Zj, Rot, L)
n = length(Xi)
r = SharedArray{Float64}((3*n,3))
#parallel for i in 1:length(Xi)
# other code...
r[(3*(i-1)+1):3*(i),:] = [0 0 rxZ; cosd(Rot[i]) -rxZ*sind(Rot[i]) 0; sind(Rot[i]) rxZ*cosd(Rot[i]) 0]
# other code...
r[(3*(i-1)+1):3*(i),:] = [rxX rxY rxZ;r21 r22 r23;r31 r32 r33]
end
end
return r
end

Matrix Translation in GLSL is infinitely stretched

I work with webgl and modify the shaders (vs.glsls and fs.glsl) to understand the GLSL and graphic programming. I have a model that I want to scale, rotate and translate. Scaling and rotating works fine but when I multiply the translation matrix, the result is weird. I know this is a very basic question, but I am missing something and I need to find it out.
my model is infinitely stretchered through the y axis.
The white area is supposed to be the eye of the model:
this is my vertex shader code:
mat4 rX = mat4 (
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 rZ = mat4 (
0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 eyeScale = mat4 (
.50,0.0,0.0,0.0,
0.0,.50,0.0,0.0,
0.0,0.0,.50,0.0,
0.0,0.0,0.0,1.0
);
mat4 eyeTrans = mat4(
1.0,0.0,0.0,0.0,
0.0,1.0,0.0,4.0,
0.0,0.0,1.0,0.0,
0.0,0.0,0.0,1.0
);
mat4 iR = eyeTrans*rZ*rX*eyeScale;
gl_Position = projectionMatrix * modelViewMatrix *iR* vec4(position, 1.0);
}
You swapped rows and columns, when you set up the translation matrix
Change it to:
mat4 eyeTrans = mat4(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 4.0, 0.0, 1.0
);
A 4*4 matrix looks like this:
c0 c1 c2 c3 c0 c1 c2 c3
[ Xx Yx Zx Tx ] [ 0 4 8 12 ]
[ Xy Yy Zy Ty ] [ 1 5 9 13 ]
[ Xz Yz Zz Tz ] [ 2 6 10 14 ]
[ 0 0 0 1 ] [ 3 7 11 15 ]
In GLSL the columns are addressed like this:
vec4 c0 = eyeTrans[0].xyzw;
vec4 c1 = eyeTrans[1].xyzw;
vec4 c2 = eyeTrans[2].xyzw;
vec4 c3 = eyeTrans[3].xyzw;
And the memory image of a 4*4 matrix looks like this:
[ Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1 ]
See further:
GLSL 4×4 Matrix Fields

Controls Implementation using Dymola

I've been having issues implementing a built-in controls algorithm (LQR) in Modelica/Dymola. I've created a simpler model that shows the problems I've been having.
Basically, I am calling LQR externally and passing it a matrix with an entry (named Ctest) that changes each time step. This Ctest is also found through an external function named findC.
The funny thing is, Dymola will run fine for if you make Ctest = 0, but if you make Ctest = 0 in an if-loop, it shows the many errors which look something like this:
Unsupported: In function Modelica_LinearSystems2.Math.Matrices.dare variable AT was declared with dimension ":".
That is not yet supported in dsmodel.c, and the function will fail if called in the model.
For example, I ran 3 different cases with the following code:
1. in function findC, if you define C as 0 (as copied below) everything runs fine.
2. if you instead make an if loop in which C will still be 0, the model won't simulate. I've copied the if loop below and commented it out.
3. if you keep findC as in case 1, but just uncomment "Real tether_l = 151.61;", it gives the same errors as case 2.
Any help would be greatly appreciated!
model SimplerModel
import Utilities;
Modelica.Mechanics.MultiBody.Joints.FreeMotion freeMotion(
useQuaternions=false,
angles_fixed=true,
r_rel_a(start={1,0,0}, fixed=true),
v_rel_a(start={0,0,0}, fixed=true),
a_rel_a(start={0,0,0}),
angles_start={0,0,0},
w_rel_a_fixed=true,
w_rel_a_start={0,0,0},
z_rel_a_fixed=false)
annotation (Placement(transformation(extent={{-50,60},{-30,80}})));
Modelica.Mechanics.MultiBody.Parts.BodyShape bodyShape(
r={0,0,1},
m=600,
I_11=100,
I_22=100,
I_33=500,
angles_start={0,0,0},
sequence_start={1,2,3},
w_0_start={0,0,0},
z_0_start={0,0,0},
r_0(start={0,0,0}),
v_0(start={0,0,0}),
a_0(start={0,0,0}),
angles_fixed=false,
w_0_fixed=false,
z_0_fixed=false,
r_CM={0,0,0.5})
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
inner Modelica.Mechanics.MultiBody.World world
annotation (Placement(transformation(extent={{-80,60},{-60,80}})));
Real[6,6] restMat=
[276533.0, 0.0, 0.0, 0.0, 0.0, 0.0;
0.0, 276533.0, 0.0, 0.0, 0.0, 0.0;
Ctest, 0.0, 319160000.0, 0.0, 0.0, 0.0;
0.0, 0.0, 0.0, 86086300000.0, 0.0, 0.0;
0.0, 0.0, 0.0, 0.0, 86086300000.0, 0.0;
0.0, 0.0, 0.0, 0.0, 0.0, 146286000.0];
Real Ctest = Utilities.findC(bodyShape.frame_a.r_0[1]);
Real K_cat[:,:] = Utilities.findK(restMat);
equation
connect(freeMotion.frame_b, bodyShape.frame_a) annotation (Line(
points={{-30,70},{-20,70},{-20,0},{-10,0}},
color={95,95,95},
thickness=0.5,
smooth=Smooth.None));
connect(world.frame_b, freeMotion.frame_a) annotation (Line(
points={{-60,70},{-50,70}},
color={95,95,95},
thickness=0.5,
smooth=Smooth.None));
annotation (uses(Modelica(version="3.2")), Diagram(coordinateSystem(
preserveAspectRatio=false, extent={{-100,-100},{100,100}}), graphics));
end SimplerModel;
function findK
function findK
import Modelica_LinearSystems2;
input Real[6,6] restoring;
Real cyl_mass = 8.21e6;
Real[6,6] mass = [1.253e7, 0,0,0,-2.99e8,0;
0,1.253e7,0,2.99e8,0,0;
0,0,1.6746e6,0,0,0;
0,2.99e8,0,9.549e9,0,0;
-2.99e8,0,0,0,9.549e9,0;
0,0,0,0,0,3.4728e7];
Real[6,6] damping = [1e5,0,0,0,0,0;
0,1e5,0,0,0,0;
0,0,1.3e5,0,0,0;
0,0,0,0,0,0;
0,0,0,0,0,0;
0,0,0,0,0,1.3e7];
Real Ipitroll = 384770000;
Real Iyaw = 291440000;
protected
Real[6,6] addMassMat = [0,0,0,0,0,0;
0,0,0,0,0,0;
0,0,cyl_mass,0,0,0;
0,0,0,Ipitroll,0,0;
0,0,0,0,Ipitroll,0;
0,0,0,0,0,Iyaw];
Real[6,6] massMat = Modelica.Math.Matrices.inv(mass + addMassMat);
Real[4, 4] A_cat = cat(1, cat(2,zeros(2,2), identity(2)), cat(2, -restoring[4:5,:]*massMat[:,4:5],-damping[4:5,:]*massMat[:,4:5]));
Real[4, 2] B_cat = cat(1, cat(1,zeros(2,2), 23/cyl_mass*identity(2)));
Real[2, 4] C_cat = cat(2, identity(2), zeros(2,2));
Real[2, 2] D_cat = zeros(2, 2);
Real[4,4] Q = [1e8,0,0,0;
0,1e8,0,0;
0,0,1e-8,0;
0,0,0,1e-8];
Real[2,2] R = [1e-9,0;
0,1e-9];
output Real K_cat[6,6];
algorithm
K_cat := Modelica_LinearSystems2.StateSpace.Design.lqr(Modelica_LinearSystems2.StateSpace(A_cat,B_cat,C_cat,D_cat), Q, R);
end findK;
function findC
function findC
input Real x;
output Real C;
//Real tether_l = 151.61;
//Real slope_ForceVsHeave = 3.1928e8;
//Real intercept_ForceVsHeave = 0;
//Real heave = tether_l - sqrt(tether_l^2 - x^2);
algorithm
//if abs(x) == 0.0 then
//C := 0;
//else C := 0;
//end if;
C:=0;
end findC;
Thanks a lot! :)
Unsupported: In function Modelica_LinearSystems2.Math.Matrices.dare
variable AT was declared with dimension ":"
means that you have to declare the dimension of your inputs, like:
...
input Integer n;
input Real[n] C;
...
because this, if compiled, will lead into an error:
...
input Real[:] C;
...
I think that one problem in your if-statement is that
if abs(x) == 0.0 then
should be replaced with
Modelica.Math.isEqual(abs(x),0,1e-15)
because you cannot compare the equality of two real numbers in Modelica.
I hope this helps,
Marco
I think Marco is right, that the problem is that the functions you are using contain variables of unknown dimensions and Dymola cannot handle this in a model. For example the dare function has:
Real AT[:, :]=transpose(A);
Try rewriting the code so that all the :'s are replaced with sizes, you may have to create functions in some cases to calculate what these sizes are going to be.
What version of Dymola are you using? I put the code, as is, into Dymola 2014 and it returned a long list of "variable ? was declared with dimension ":"."
Also I think all Real variables in functions should be protected.
Hopefully fixing this will sort out the problem.
This is the code after modifying according to the two answers (declare sizes of all matrices, protect Reals in functions, change if condition):
model SimplerModel
import OnWind.Components.Substructure.Utilities;
Modelica.Mechanics.MultiBody.Joints.FreeMotion freeMotion(
useQuaternions=false,
angles_fixed=true,
r_rel_a(start={0.5,0,0}, fixed=true),
v_rel_a(start={0,0,0}, fixed=true),
a_rel_a(start={0,0,0}),
angles_start={0,0,0},
w_rel_a_fixed=true,
w_rel_a_start={0,0,0},
z_rel_a_fixed=false)
annotation (Placement(transformation(extent={{-50,60},{-30,80}})));
Modelica.Mechanics.MultiBody.Parts.BodyShape bodyShape
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
inner Modelica.Mechanics.MultiBody.World world
annotation (Placement(transformation(extent={{-80,60},{-60,80}})));
//input Integer hi = 1;
Real[6,6] restMat=
[276533.0, 0.0, 0.0, 0.0, 0.0, 0.0;
0.0, 276533.0, 0.0, 0.0, 0.0, 0.0;
Ctest, 0.0, 319160000.0, 0.0, 0.0, 0.0;
0.0, 0.0, 0.0, 86086300000.0, 0.0, 0.0;
0.0, 0.0, 0.0, 0.0, 86086300000.0, 0.0;
0.0, 0.0, 0.0, 0.0, 0.0, 146286000.0];
Real Ctest = Utilities.findC(bodyShape.frame_b.r_0[1]);
Real K_cat[2,4] = Utilities.findK(restMat);
equation
connect(freeMotion.frame_b, bodyShape.frame_a) annotation (Line(
points={{-30,70},{-20,70},{-20,0},{-10,0}},
color={95,95,95},
thickness=0.5,
smooth=Smooth.None));
connect(world.frame_b, freeMotion.frame_a) annotation (Line(
points={{-60,70},{-50,70}},
color={95,95,95},
thickness=0.5,
smooth=Smooth.None));
annotation (uses(Modelica(version="3.2")), Diagram(coordinateSystem(
preserveAspectRatio=false, extent={{-100,-100},{100,100}}), graphics));
end SimplerModel;
function findK
function findK
import Modelica_LinearSystems2;
input Real[6,6] restoring;
protected
Real cyl_mass = 8.21e6;
Real[6,6] mass = [1.253e7, 0,0,0,-2.99e8,0;
0,1.253e7,0,2.99e8,0,0;
0,0,1.6746e6,0,0,0;
0,2.99e8,0,9.549e9,0,0;
-2.99e8,0,0,0,9.549e9,0;
0,0,0,0,0,3.4728e7];
Real[6,6] damping = [1e5,0,0,0,0,0;
0,1e5,0,0,0,0;
0,0,1.3e5,0,0,0;
0,0,0,0,0,0;
0,0,0,0,0,0;
0,0,0,0,0,1.3e7];
Real Ipitroll = 384770000;
Real Iyaw = 291440000;
Real[6,6] addMassMat = [0,0,0,0,0,0;
0,0,0,0,0,0;
0,0,cyl_mass,0,0,0;
0,0,0,Ipitroll,0,0;
0,0,0,0,Ipitroll,0;
0,0,0,0,0,Iyaw];
Real[6,6] massMat = Modelica.Math.Matrices.inv(mass + addMassMat);
Real[4, 4] A_cat = cat(1, cat(2,zeros(2,2), identity(2)), cat(2, -restoring[4:5,:]*massMat[:,4:5],-damping[4:5,:]*massMat[:,4:5]));
Real[4, 2] B_cat = cat(1, cat(1,zeros(2,2), 23/cyl_mass*identity(2)));
Real[2, 4] C_cat = cat(2, identity(2), zeros(2,2));
Real[2, 2] D_cat = zeros(2, 2);
Real[4,4] Q = [1e8,0,0,0;
0,1e8,0,0;
0,0,1e-8,0;
0,0,0,1e-8];
Real[2,2] R = [1e-9,0;
0,1e-9];
output Real K_cat[2,4];
algorithm
K_cat := Modelica_LinearSystems2.StateSpace.Design.lqr(Modelica_LinearSystems2.StateSpace(A_cat,B_cat,C_cat,D_cat), Q, R);
end findK;
function findC
function findC
input Real x;
output Real C;
//Real tether_l = 151.61;
algorithm
C:=0;
/* if Modelica.Math.isEqual(abs(x),0,1e-15) then
C := 0;
else C := 0;
end if;
*/
end findC;
This should run as-is. But I've commented out necessary parts of function findC in order to make it work.
In findC, uncommenting either the declaration of unused variable tether_l (which is needed in my actual code) or the if statement (also needed in my code, but written here as a trivial statement just for this simpler example) will cause it to fail.
Just to summarize, Dymola produces a long list of "Unsupported: In function __ variable __ was declared with dimension ":"". But all of these variables are actually Dymola declared in Dymola functions. Some changes cause it to work, but these changes are unrelated to the matrices.
Would appreciate any ideas or advice! :)
Thanks

Resources