Why is my depth testing not working in PyOpenGL - cube

I'm quite new in 3D graphics so I'm just learning :-D. I wanted to create a cube as my first project. I chose PyOpenGl and ran into the following problem: Depth testing didn't work for me. I searched the tutorials on the internet but nothing helped me find a bug in my code. Can anyone advise me? Here is my code:
import glfw
import math
from OpenGL.GL import *
glfw.init()
window = glfw.create_window(800, 600, "First Project", None, None)
glfw.set_window_pos(window, 400, 200)
glfw.make_context_current(window)
glEnableClientState(GL_VERTEX_ARRAY)
angle = 0.0005
cube = [
[-0.5, 0.5, 0],
[ 0.5, 0.5, 0],
[ 0.5, -0.5, 0],
[-0.5, -0.5, 0],
[-0.5, 0.5, -1],
[ 0.5, 0.5, -1],
[ 0.5, -0.5, -1],
[-0.5, -0.5, -1]
]
def RotateMatrix3DAroundX(x, y, z, angle):
Rx = 1 * x + 0 * y + 0 * z
Ry = 0 * x + math.cos(angle) * y + (-math.sin(angle) * z)
Rz = 0 * x + math.sin(angle) * y + math.cos(angle) * z
return [Rx, Ry, Rz]
def Drawing():
glBegin(GL_QUADS)
glColor3f(255, 0, 0)
glVertex3f(cube[0][0], cube[0][1], cube[0][2])
glVertex3f(cube[1][0], cube[1][1], cube[1][2])
glVertex3f(cube[1][0], cube[1][1], cube[1][2])
glVertex3f(cube[2][0], cube[2][1], cube[2][2])
glVertex3f(cube[2][0], cube[2][1], cube[2][2])
glVertex3f(cube[3][0], cube[3][1], cube[3][2])
glVertex3f(cube[3][0], cube[3][1], cube[3][2])
glVertex3f(cube[0][0], cube[0][1], cube[0][2])
glColor3f(0, 255, 0)
glVertex3f(cube[4][0], cube[4][1], cube[4][2])
glVertex3f(cube[5][0], cube[5][1], cube[5][2])
glVertex3f(cube[5][0], cube[5][1], cube[5][2])
glVertex3f(cube[6][0], cube[6][1], cube[6][2])
glVertex3f(cube[6][0], cube[6][1], cube[6][2])
glVertex3f(cube[7][0], cube[7][1], cube[7][2])
glVertex3f(cube[7][0], cube[7][1], cube[7][2])
glVertex3f(cube[4][0], cube[4][1], cube[4][2])
glColor3f(0, 0, 255)
glVertex3f(cube[0][0], cube[0][1], cube[0][2])
glVertex3f(cube[4][0], cube[4][1], cube[4][2])
glVertex3f(cube[4][0], cube[4][1], cube[4][2])
glVertex3f(cube[7][0], cube[7][1], cube[7][2])
glVertex3f(cube[7][0], cube[7][1], cube[7][2])
glVertex3f(cube[3][0], cube[3][1], cube[3][2])
glVertex3f(cube[3][0], cube[3][1], cube[3][2])
glVertex3f(cube[0][0], cube[0][1], cube[0][2])
glColor3f(150, 150, 150)
glVertex3f(cube[0][0], cube[0][1], cube[0][2])
glVertex3f(cube[4][0], cube[4][1], cube[4][2])
glVertex3f(cube[4][0], cube[4][1], cube[4][2])
glVertex3f(cube[5][0], cube[5][1], cube[5][2])
glVertex3f(cube[5][0], cube[5][1], cube[5][2])
glVertex3f(cube[1][0], cube[1][1], cube[1][2])
glVertex3f(cube[1][0], cube[1][1], cube[1][2])
glVertex3f(cube[0][0], cube[0][1], cube[0][2])
glColor3f(150, 0, 150)
glVertex3f(cube[1][0], cube[1][1], cube[1][2])
glVertex3f(cube[5][0], cube[5][1], cube[5][2])
glVertex3f(cube[5][0], cube[5][1], cube[5][2])
glVertex3f(cube[6][0], cube[6][1], cube[6][2])
glVertex3f(cube[6][0], cube[6][1], cube[6][2])
glVertex3f(cube[2][0], cube[2][1], cube[2][2])
glVertex3f(cube[2][0], cube[2][1], cube[2][2])
glVertex3f(cube[1][0], cube[1][1], cube[1][2])
glColor3f(150, 150, 0)
glVertex3f(cube[3][0], cube[3][1], cube[3][2])
glVertex3f(cube[7][0], cube[7][1], cube[7][2])
glVertex3f(cube[7][0], cube[7][1], cube[7][2])
glVertex3f(cube[6][0], cube[6][1], cube[6][2])
glVertex3f(cube[6][0], cube[6][1], cube[6][2])
glVertex3f(cube[2][0], cube[2][1], cube[2][2])
glVertex3f(cube[2][0], cube[2][1], cube[2][2])
glVertex3f(cube[3][0], cube[3][1], cube[3][2])
glEnd()
for i in range(8):
cube[i] = RotateMatrix3DAroundX(cube[i][0], cube[i][1], cube[i][2], angle)
while not(glfw.window_should_close(window)):
glfw.poll_events()
glClearColor(0, 0, 0, 0)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
Drawing()
glfw.swap_buffers(window)
glfw.terminate()
Here is image of result I am getting:
image_of_my_result

Parts of your cube are clipped by the near and far plane of the viewing volume. Set an Orthographic projection with a larger distance to the near and far plane:
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-1, 1, -1, 1, -2, 2)
glMatrixMode(GL_MODELVIEW)
while not(glfw.window_should_close(window)):
# [...]
Instead of changing the cube vertices, use a rotation matrix:
def Drawing():
# [...]
glRotate(math.degrees(angle), 1, 0, 0)
# DELETE
#for i in range(8):
# cube[i] = RotateMatrix3DAroundX(cube[i][0], cube[i][1], cube[i][2], angle)

Related

How Do I Fix This Numpy Error: Too Many Indices For Array?

I am working with some old code that works in Python2 but raises an error in Python3. The error stems from an np array in the module. The array is below.
if I assign the np array to a variable called test, and call test[:,0], I get an error "IndexError: too many indices for array."
The byte array is created using an np.asarray() function on bytes coming from a calibration table on a piece of hardware. This error is particularly confusing to me, as it works perfectly fine in Python2.
How can I fix this issue?
>>>test=b'[[0, 0, 0], [0.0, 0.01, -1.0], [0.1, 0.01, 8.0], [0.2, 0.02, 10.0], [0.3, 0.02, 12.0], [0.4, 0.03, 14.0], [0.5, 0.04, 16.0], [0.6, 0.05, 18.0], [0.7, 0.06, 19.0], [0.8, 0.08, 21.0], [0.9, 0.11, 23.0], [1.0, 0.24, 24.0], [1.1, 3.82, 25.0], [1.2, 9.09, 26.0], [1.3, 14.36, 27.0], [1.4, 19.78, 28.0], [1.5, 25.11, 30.0], [1.6, 30.57, 31.0], [1.7, 36.01, 31.0], [1.8, 41.51, 33.0], [1.9, 47.07, 34.0], [2.0, 52.57, 35.0], [2.1, 58.13, 36.0], [2.2, 63.74, 37.0], [2.3, 69.46, 37.0], [2.4, 74.89, 38.0], [2.5, 80.63, 39.0]]'
>>>test2 = np.asarray(test)
>>>test2[:,0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: too many indices for array
EDIT: Added code for clarification. Also, the issue seems to be that in Python3, type(test) = bytes, but in python2 type(test) = list.
Your code sample is incomplete. I suppose it shoud be:
test = b'[...]'
(... stands for your content between brackets, I added ' at the end).
Note that test is of bytes type.
When you run test2.ndim the result is 0, so (in the recent version of
Numpy) it is a 0-D array.
To get its content (a scalar), you can run: test2.item(), getting
back a bytes object:
b'[...]'
You can transcode it into an "ordinary" (UTF-8) string, running:
test2.item().decode('utf-8')
but it is still a string, not an array.
To get "ordinary" 2-D Numpy array, you can import ast and then run:
test3 = np.array(ast.literal_eval(test2.item().decode('utf-8')))
(ast.literal_eval is more safe than "ordinary" eval) or starting
from test:
test3 = np.array(ast.literal_eval(test.decode('utf-8')))
Now you can run: test3[:,0], getting what you want, i.e.:
array([0. , 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1,
1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4,
2.5])
Are you sure this working in Py2?
In [290]: test=b'[[0, 0, 0], [0.0, 0.01, -1.0], [0.1, 0.01, 8.0], [0.2, 0.02, 10.0], [0.3
...: , 0.02, 12.0], [0.4, 0.03, 14.0], [0.5, 0.04, 16.0], [0.6, 0.05, 18.0], [0.7, 0
...: .06, 19.0], [0.8, 0.08, 21.0], [0.9, 0.11, 23.0], [1.0, 0.24, 24.0], [1.1, 3.82
...: , 25.0], [1.2, 9.09, 26.0], [1.3, 14.36, 27.0], [1.4, 19.78, 28.0], [1.5, 25.11
...: , 30.0], [1.6, 30.57, 31.0], [1.7, 36.01, 31.0], [1.8, 41.51, 33.0], [1.9, 47.0
...: 7, 34.0], [2.0, 52.57, 35.0], [2.1, 58.13, 36.0], [2.2, 63.74, 37.0], [2.3, 69.
...: 46, 37.0], [2.4, 74.89, 38.0], [2.5, 80.63, 39.0]]'
In [291]: test
Out[291]: b'[[0, 0, 0], [0.0, 0.01, -1.0], [0.1, 0.01, 8.0], [0.2, 0.02, 10.0], [0.3, 0.02, 12.0], [0.4, 0.03, 14.0], [0.5, 0.04, 16.0], [0.6, 0.05, 18.0], [0.7, 0.06, 19.0], [0.8, 0.08, 21.0], [0.9, 0.11, 23.0], [1.0, 0.24, 24.0], [1.1, 3.82, 25.0], [1.2, 9.09, 26.0], [1.3, 14.36, 27.0], [1.4, 19.78, 28.0], [1.5, 25.11, 30.0], [1.6, 30.57, 31.0], [1.7, 36.01, 31.0], [1.8, 41.51, 33.0], [1.9, 47.07, 34.0], [2.0, 52.57, 35.0], [2.1, 58.13, 36.0], [2.2, 63.74, 37.0], [2.3, 69.46, 37.0], [2.4, 74.89, 38.0], [2.5, 80.63, 39.0]]'
In [292]: np.asarray(test)
Out[292]:
array(b'[[0, 0, 0], [0.0, 0.01, -1.0], [0.1, 0.01, 8.0], [0.2, 0.02, 10.0], [0.3, 0.02, 12.0], [0.4, 0.03, 14.0], [0.5, 0.04, 16.0], [0.6, 0.05, 18.0], [0.7, 0.06, 19.0], [0.8, 0.08, 21.0], [0.9, 0.11, 23.0], [1.0, 0.24, 24.0], [1.1, 3.82, 25.0], [1.2, 9.09, 26.0], [1.3, 14.36, 27.0], [1.4, 19.78, 28.0], [1.5, 25.11, 30.0], [1.6, 30.57, 31.0], [1.7, 36.01, 31.0], [1.8, 41.51, 33.0], [1.9, 47.07, 34.0], [2.0, 52.57, 35.0], [2.1, 58.13, 36.0], [2.2, 63.74, 37.0], [2.3, 69.46, 37.0], [2.4, 74.89, 38.0], [2.5, 80.63, 39.0]]',
dtype='|S517')
Did you look at test2 before trying to use it? You have just wrapped one big string in np.array; look at the shape and dtype.
You can make an array from the text if applied as:
In [293]: np.array([[0, 0, 0], [0.0, 0.01, -1.0], [0.1, 0.01, 8.0], [0.2, 0.02, 10.0], [0
...: .3, 0.02, 12.0], [0.4, 0.03, 14.0], [0.5, 0.04, 16.0], [0.6, 0.05, 18.0], [0.7,
....
...: 9.46, 37.0], [2.4, 74.89, 38.0], [2.5, 80.63, 39.0]])
Out[293]:
array([[ 0.000e+00, 0.000e+00, 0.000e+00],
[ 0.000e+00, 1.000e-02, -1.000e+00],
[ 1.000e-01, 1.000e-02, 8.000e+00],
[ 2.000e-01, 2.000e-02, 1.000e+01],
....
[ 2.500e+00, 8.063e+01, 3.900e+01]])
But this is quite different from passing a string (even a py2 bytestring) to np.array.
You could use eval to convert the bytestring to a list of lists, and then make the array from that:
In [298]: eval(test)
Out[298]:
[[0, 0, 0],
[0.0, 0.01, -1.0],
[0.1, 0.01, 8.0],
[0.2, 0.02, 10.0],
...
[2.5, 80.63, 39.0]]
In [299]: np.array(eval(test))
Out[299]:
array([[ 0.000e+00, 0.000e+00, 0.000e+00],
[ 0.000e+00, 1.000e-02, -1.000e+00],
[ 1.000e-01, 1.000e-02, 8.000e+00],
...
[ 2.500e+00, 8.063e+01, 3.900e+01]])

Simple structure initialization in Swift (4)?

I'm new to Swift and trying to port some code. I have this from an old project:
typedef struct {
float Position[3];
float Normal[3];
float TexCoord[2]; // New
} iconVertex;
const iconVertex iconVertices[] = {
{{0.0,0.0, 0.0}, {0, 0, 1.0}, {0, 0}},
{{1.0, 0.0, 0.0}, {0, 0, 1.0}, {1, 0}},
{{0.0, 1.0, 0.0}, {0, 0, 1.0}, {0, 1}},
{{1.0, 1.0, 0.0}, {0, 0, 1.0}, {1, 1}},
};
Is there any way to do that same array initialization in Swift?
Thanks!
In Swift you can use Structs to define your objects and create an init method that receives the parameters that you need to initialise.
struct IconVertex {
var position: [Double]
var normal: [Double]
var textCoord: [Double]
init(position: [Double], normal: [Double], textCoord: [Double]) {
self.position = position
self.normal = normal
self.textCoord = textCoord
}
}
let iconVertices: [IconVertex] = [
IconVertex(position: [0.0,0.0, 0.0], normal: [0, 0, 1.0], textCoord: [0, 0]),
IconVertex(position: [1.0, 0.0, 0.0], normal: [0, 0, 1.0], textCoord: [1, 0]),
IconVertex(position: [0.0, 1.0, 0.0], normal: [0, 0, 1.0], textCoord: [0, 1]),
IconVertex(position: [1.0, 1.0, 0.0], normal: [0, 0, 1.0], textCoord: [1, 1])]

Array after an element is > 0 change all elements to that value until next non zero value

I have an array that is for example
[0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
How can I change the element with 0 value if the previous value > 0? so
[0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
becomes
[0.0, 0.0, 55.0, 55.0, 55.0, 55.0, 55.0, 22.0, 22.0, 55.0]
I have tried the following and it removes the zeros and nothing else.
func weightArrayRemovedZero(array: [Double])->[Double]{
var arrayToAlter = [Double]()
for(index,item) in array.enumerated() {
print("The \(item) is at index:\(index)")
if item == 0.0 {
if index > 0 && index < array.count - 1 {
if array[index - 1] != 0.0 {
let nonZeroElement = array[index - 1]
arrayToAlter.append(nonZeroElement)
}
}
} else {
arrayToAlter.append(item)
}
}
return arrayToAlter
}
map seems to be the natural approach to me:
var last = 0.0
let mapped = values.map { elem -> (Double) in
last = elem > 0.0 ? elem : last
return last
}
Generally speaking, map is your go to when you want to change one collection into another collection with a one-to-one element mapping.
Try this out
var array = [0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
array.enumerated().forEach {
array[$0] = $1 == 0 &&
array.indices.contains($0 - 1) &&
array[$0 - 1] > 0 ? array[$0 - 1] : $1
}
print(array)
Another option:
var array = [0.0, 0.0, 55.0, 0.0, 0.0, 55.0, 55.0, 22.0, 0.0, 55.0]
for i in array.indices {
if i == 0 { continue }
if array[i] == 0 && array[i-1] != 0 {
array[i] = array[i-1]
}
}
// [0, 0, 55, 55, 55, 55, 55, 22, 22, 55]

Modelica: Program a static solver to converge to a solution during the simulation. CFD example

Generic question:
I work on Modelica with OpenModelica. I would like to program my own solver in Modelica to converge to a solution because I think OpenModelica can't solve my problem. Is it possible?
Specific case:
I developed a model of a separation of air in fluid dynamic component. My model is based on a data table which provide the coefficient of pressure loss for each branche depending of the velocities in the component and the parameter "section".
My model works well when I use MassFlow sources but not when I use only Pressure source. See the pictures below to understand the connection with my component:
http://www.casimages.com/img.php?i=140620024048704083.png
http://www.casimages.com/img.php?i=140620024137384886.png
The code of my model "separation" is this one:
model separation
replaceable package Medium = Modelica.Media.Interfaces.PartialMedium "Medium in the component";
Modelica.Fluid.Interfaces.FluidPort_a port_a(redeclare package Medium = Medium);
Modelica.Fluid.Interfaces.FluidPort_b port_b2(redeclare package Medium = Medium);
Modelica.Fluid.Interfaces.FluidPort_b port_b1(redeclare package Medium = Medium);
Modelica.Blocks.Tables.CombiTable2D coeff_PDC1(table = [0, 0, 0.4, 0.5, 0.6, 0.7, 0.8, 1; 0, 1, 1, 1, 1, 1, 1, 1; 0.1, 0.81, 0.81, 0.81, 0.81, 0.81, 0.81, 0.81; 0.2, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64; 0.3, 0.5, 0.5, 0.52, 0.52, 0.5, 0.5, 0.5; 0.4, 0.36, 0.36, 0.4, 0.38, 0.37, 0.36, 0.36; 0.5, 0.25, 0.25, 0.3, 0.28, 0.26, 0.25, 0.25; 0.6, 0.16, 0.16, 0.23, 0.2, 0.18, 0.16, 0.16; 0.8, 0.04, 0.04, 0.16, 0.12, 0.07, 0.04, 0.04; 1, 0.001, 0.001, 0.2, 0.1, 0.05, 0.001, 0.001; 1.2, 0.07, 0.07, 0.36, 0.21, 0.14, 0.07, 0.07; 1.4, 0.39, 0.39, 0.78, 0.59, 0.49, 50, 50; 1.6, 0.9, 0.9, 1.36, 1.15, 50, 50, 50; 1.8, 1.78, 1.78, 2.43, 50, 50, 50, 50; 2, 3.2, 3.2, 4, 50, 50, 50, 50]);
Modelica.Blocks.Tables.CombiTable1Ds coeff_PDC2( table = [0.1, 1; 0.2, 1; 0.3, 1; 0.4, 1; 0.5, 1; 0.6, 1; 0.8, 1; 1,1; 1.2, 1; 1.4, 1; 1.6, 1; 1.8, 1; 2, 1]);
Real dp_b1 "en Pa, perte de charge entre les ports a1 et b";
Real dp_b2 "en Pa, perte de charge entre les ports a2 et b";
Modelica.SIunits.Velocity v_a(start = 0);
Modelica.SIunits.Velocity v_b1(start = 0);
Modelica.SIunits.Velocity v_b2(start = 0);
parameter Real rho=1.2;
parameter Modelica.SIunits.Area surface_b1 = 1;
parameter Modelica.SIunits.Area surface_b2 = 1;
parameter Modelica.SIunits.Area surface_a = 2;
equation
coeff_PDC1.u1 = if noEvent(abs(v_a) > 0) then v_b1/v_a else 1;
coeff_PDC1.u2 = surface_b1/surface_a;
coeff_PDC2.u = if noEvent(abs(v_a) > 0) then v_b2/v_a else 1;
v_a = abs(port_a.m_flow)/rho/surface_a;
v_b1 = abs(port_b1.m_flow)/rho/surface_b1;
v_b2 = abs(port_b2.m_flow)/rho/surface_b2;
port_b1.p - port_a.p = dp_b1;
dp_b1 = 1/2*coeff_PDC1.y*port_b1.m_flow^2/surface_b1^2/rho;
port_b2.p - port_a.p = dp_b2;
dp_b2 = 1/2*coeff_PDC2.y[1]*port_b2.m_flow^2/surface_b2^2/rho;
port_b1.m_flow + port_b2.m_flow + port_a.m_flow = 0;
port_b1.Xi_outflow = inStream(port_a.Xi_outflow);
port_b2.Xi_outflow = inStream(port_a.Xi_outflow);
port_a.Xi_outflow = inStream(port_b1.Xi_outflow);
port_b1.C_outflow = inStream(port_a.C_outflow);
port_b2.C_outflow = inStream(port_a.C_outflow);
port_a.C_outflow = inStream(port_b1.C_outflow);
port_b1.h_outflow = inStream(port_a.h_outflow);
port_b2.h_outflow = inStream(port_a.h_outflow);
port_a.h_outflow = inStream(port_b1.h_outflow);
end separation;
It's a "nonlinear system" error when I connect this model to 3 Pressure components (set to Patm +10000Pa for the source and Patm for the sink). This model works well with the MassFlow sink. Why? Should I develop my own solver to solve it? If yes how?
Your question is not completely clear. But, I think what you are asking if given a value of dp, at any time, can modelica solve for v, when there is a table for the relationship of K and v? If I understand your variables correctly, this should do it:
model test5
Real v "fluid velocity";
Real K "Pressure loss coefficient";
Real dp =0.5 "Pressure drop"; //Example value
Real rho = 1.0 "density" ;
Modelica.Blocks.Tables.CombiTable2D coeff_PDC1(table = [0, 0, 0.4, 0.5, 0.6, 0.7, 0.8, 1; 0, 1, 1, 1, 1, 1, 1, 1; 0.1, 0.81, 0.81, 0.81, 0.81, 0.81, 0.81, 0.81; 0.2, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64; 0.3, 0.5, 0.5, 0.52, 0.52, 0.5, 0.5, 0.5; 0.4, 0.36, 0.36, 0.4, 0.38, 0.37, 0.36, 0.36; 0.5, 0.25, 0.25, 0.3, 0.28, 0.26, 0.25, 0.25; 0.6, 0.16, 0.16, 0.23, 0.2, 0.18, 0.16, 0.16; 0.8, 0.04, 0.04, 0.16, 0.12, 0.07, 0.04, 0.04; 1, 0, 0, 0.2, 0.1, 0.05, 0, 0; 1.2, 0.07, 0.07, 0.36, 0.21, 0.14, 0.07, 0.07; 1.4, 0.39, 0.39, 0.78, 0.59, 0.49, 50, 50; 1.6, 0.9, 0.9, 1.36, 1.15, 50, 50, 50; 1.8, 1.78, 1.78, 2.43, 50, 50, 50, 50; 2, 3.2, 3.2, 4, 50, 50, 50, 50]);
equation
coeff_PDC1.u2 = 0.5;
dp = 0.5 * K * rho * v ^ 2;
v = coeff_PDC1.u1;
K = coeff_PDC1.y;
end test5;
When I run this, it solves for v, given a value of dp. Is that what you want?
OpenModelica gives a hint that the original model is bad:
Error: Initialization problem is structurally singular, error found sorting equations
1: algorithm
v := 0.0;
2: algorithm
K := 1.0;
while v > 0.01 + $PRE.v loop
v := (10.0 / K) ^ 0.5;
K := 1.0 + v ^ 2.0;
end while;
v is defined in both an initial algorithm and an algorithm section. initial algorithms are only supposed to be used for parameters or states (both der(x) and x need to be specified in the initial step). Luckily, you can specify v(start=0), and v will be initialized to 0 at the start of an algorithm section that assigns to v.
After that is resolved, the model compiles and simulates. Although as others stated, algorithm sections are ugly and should be avoided at all costs in Modelica.
I'm not sure I understand the problem 100%. You said that you could not express it analytically. But can you express the relationship between K and v as a Modelica function? If so, you can use the inverse annotation to supply an inverse function. In this way, the tool will use the most efficient version of the function and can avoid having to do any non-linear iteration. But this assumes you can formulate the inverse function. It wasn't clear to me, from your explanation, whether you could or not.

MongoDB - Query with operations against array parameter elements

I’m new to MongoDB and I’m trying to get my head around whether I can perform this query conveniently and with decent performance using MongoDB. I’d like to pass numeric and array parameters to a query and use them to perform element by element operations on array values in each document in the collection. Is this possible?
e.g. A collection contains documents like the following:
{
"name" : "item1",
"m" : 5.2,
"v" : 1.1,
"data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
"data2" : [ 0, -1, 0, 1, 1, 0 ]
}
And I have another "search" document that might look something like this:
{
"x" : 8,
"K" : 1,
"dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
"dataB" : [ 0, -2, 0, 1, 1, 0 ]
}
I want to run a query, or map-reduce, using the above search document against the collection above that returns a collection containing:
{
"name",
"y" = fn(m, v, x, K) = Kvx^(1/m) (not the real formula but just an example)
"dataF" = Max(i=0..9) {data1[i] * dataA[i] }
"dataS" = Sum(j=0..5) {data2[j] * dataB[j] }
}
where y>0
So for the above example, the result returned would be
{
"name" : "item1",
"y" : 1 * 1.1 * 8^5.2 = 1.641
"dataF" : Max(..., 0.4*0.5, 0.1*1, 0 * 0.5 ) = 0.2
"dataS" : 0*0 + (-1)*(-2) + 0*0 + 1*1 + 1*1 + 0*0 = 4
}
Is this going to be possible/convenient using MongoDB?
Note: In my application there will be more standard criteria included in the search using standard MongoDB operations so I was hoping to include the above processing in the query and avoid doing it on the client.
Here's a map/reduce version:
db.data.save({
"name" : "item1",
"m" : 5.2,
"v" : 1.1,
"data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
"data2" : [ 0, -1, 0, 1, 1, 0 ]
});
db.data.mapReduce( function() {
var searchdoc = {
"x" : 8,
"K" : 1,
"dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
"dataB" : [ 0, -2, 0, 1, 1, 0 ]
};
var result = {name: this.name};
result.y = searchdoc.K * this.v * Math.pow(searchdoc.x, 1 / this.m);
if(result.y > 0) {
result.dataF = 0;
for(i=0;i<this.data1.length;i++) {
var f = this.data1[i] * searchdoc.dataA[i];
if(f > result.dataF) {
result.dataF = f;
}
}
result.dataS = 0;
for(i=0;i<this.data2.length;i++) {
var s = this.data2[i] * searchdoc.dataB[i];
result.dataS += s;
}
emit(this.name, result);
}
}, function(key, values){}, {out: {inline: 1}});
result:
{
"results" : [
{
"_id" : "item1",
"value" : {
"name" : "item1",
"y" : 1.640830939540542,
"dataF" : 0.2,
"dataS" : 4
}
}
],
"timeMillis" : 0,
"counts" : {
"input" : 1,
"emit" : 1,
"reduce" : 0,
"output" : 1
},
"ok" : 1,
}
This is the shell version:
db.data.save({
"name" : "item1",
"m" : 5.2,
"v" : 1.1,
"data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ],
"data2" : [ 0, -1, 0, 1, 1, 0 ]
});
var searchdoc = {
"x" : 8,
"K" : 1,
"dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5],
"dataB" : [ 0, -2, 0, 1, 1, 0 ]
};
var search = function(searchdoc) {
db.data.find().forEach(function(obj) {
var result = {name:obj.name};
result.y = searchdoc.K * obj.v * Math.pow(searchdoc.x, 1 / obj.m);
if( result.y > 0 ) {
result.dataF = 0;
for(i=0;i<obj.data1.length;i++) {
var f = obj.data1[i] * searchdoc.dataA[i];
if(f > result.dataF) {
result.dataF = f;
}
}
result.dataS = 0;
for(i=0;i<obj.data2.length;i++) {
var s = obj.data2[i] * searchdoc.dataB[i];
result.dataS += s;
}
db.results.save(result);
}
});
}
search(searchdoc);
db.results.find();
{ "_id" : ObjectId("4f08ffe4264d23670eeaaadf"), "name" : "item1", "y" : 1.640830939540542, "dataF" : 0.2, "dataS" : 4 }

Resources