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

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.

Related

Rotate layer Rubik's Cube

I'm programming a rubik cube in c with SDL and OpenGl. I have done all the implementation, except the rotation of a layer move (now if i press 'r' or 'f', for example, right or front layers change its colours). I don't really know how to implement the rotation of a layer.
Here is my render implementation which draws the cube.
Note: mov is 7 if i want to rotate clockwise right layer, 8 if i want to rotate left layer etc, **s is an array with the rgb color of each sticker of the cube
static void
Render(int mov, double **s)
{
static float color[8][3] = {
{1.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{0.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 1.0, 1.0},
{1.0, 1.0, 1.0},
{1.0, 0.0, 1.0},
{0.0, 0.0, 1.0}
};
static float cube[56][3] = {
// Cara 1
{0.6, 0.6, 0.6},
{0.6, 0.6, 0.2},
{0.6, 0.6, -0.2},
{0.6, 0.6, -0.6},
{0.6, 0.2, -0.6},
{0.6, -0.2, -0.6},
{0.6, -0.6, -0.6},
{0.6, -0.6, -0.2},
{0.6, -0.6, 0.2},
{0.6, -0.6, 0.6},
{0.6, -0.2, 0.6},
{0.6, 0.2, 0.6},
{0.6, 0.2, 0.2},
{0.6, 0.2, -0.2},
{0.6, -0.2, -0.2},
{0.6, -0.2, 0.2},
// Cara 2
{0.2, 0.6, 0.6},
{-0.2, 0.6, 0.6},
{-0.6, 0.6, 0.6},
{-0.6, 0.6, 0.2},
{-0.6, 0.6, -0.2},
{-0.6, 0.6, -0.6},
{-0.2, 0.6, -0.6}, // 22
{0.2, 0.6, -0.6},
{0.2, 0.6, -0.2},
{0.2, 0.6, 0.2},
{-0.2, 0.6, 0.2},
{-0.2, 0.6, -0.2}, // 27
// Cara 3
{-0.6, 0.2, 0.6},
{-0.6, 0.2, 0.2},
{-0.6, 0.2, -0.2},
{-0.6, 0.2, -0.6},
{-0.6, -0.2, -0.6},
{-0.6, -0.6, -0.6}, // 33
{-0.6, -0.6, -0.2},
{-0.6, -0.6, 0.2},
{-0.6, -0.6, 0.6},
{-0.6, -0.2, 0.6},
{-0.6, -0.2, 0.2},
{-0.6, -0.2, -0.2}, // 39
// Cara 4
{-0.2, -0.6, 0.6},
{-0.2, -0.6, 0.2},
{-0.2, -0.6, -0.2},
{-0.2, -0.6, -0.6},
{0.2, -0.6, -0.6}, // 44
{0.2, -0.6, -0.2},
{0.2, -0.6, 0.2},
{0.2, -0.6, 0.6}, // 47
// Cara 5
{0.2, 0.2, 0.6},
{0.2, -0.2, 0.6},
{-0.2, -0.2, 0.6},
{-0.2, 0.2, 0.6},
// Cara 6
{0.2, 0.2, -0.6},
{0.2, -0.2, -0.6},
{-0.2, -0.2, -0.6},
{-0.2, 0.2, -0.6}
};
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
// Cara 1
glColor3f(s[2][0], s[2][1], s[2][2]);
glVertex3fv(cube[8]);
glVertex3fv(cube[9]);
glVertex3fv(cube[10]);
glVertex3fv(cube[15]);
glColor3f(s[5][0], s[5][1], s[5][2]);
glVertex3fv(cube[10]);
glVertex3fv(cube[11]);
glVertex3fv(cube[12]);
glVertex3fv(cube[15]);
glColor3f(s[8][0], s[8][1], s[8][2]);
glVertex3fv(cube[0]);
glVertex3fv(cube[1]);
glVertex3fv(cube[12]);
glVertex3fv(cube[11]); // ST2
glColor3f(s[1][0], s[1][1], s[1][2]);
glVertex3fv(cube[7]);
glVertex3fv(cube[8]);
glVertex3fv(cube[15]);
glVertex3fv(cube[14]);
glColor3f(s[4][0], s[4][1], s[4][2]);
glVertex3fv(cube[12]);
glVertex3fv(cube[13]);
glVertex3fv(cube[14]);
glVertex3fv(cube[15]);
glColor3f(s[7][0], s[7][1], s[7][2]);
glVertex3fv(cube[1]);
glVertex3fv(cube[2]);
glVertex3fv(cube[13]);
glVertex3fv(cube[12]);
glColor3f(s[0][0], s[0][1], s[0][2]);
glVertex3fv(cube[5]);
glVertex3fv(cube[6]);
glVertex3fv(cube[7]);
glVertex3fv(cube[14]);
glColor3f(s[3][0], s[3][1], s[3][2]);
glVertex3fv(cube[4]);
glVertex3fv(cube[5]);
glVertex3fv(cube[14]);
glVertex3fv(cube[13]);
glColor3f(s[6][0], s[6][1], s[6][2]);
glVertex3fv(cube[2]);
glVertex3fv(cube[3]);
glVertex3fv(cube[4]);
glVertex3fv(cube[13]);
// Cara 2
glColor3f(s[11][0], s[11][1], s[11][2]);
glVertex3fv(cube[0]);
glVertex3fv(cube[1]);
glVertex3fv(cube[25]);
glVertex3fv(cube[16]);
glColor3f(s[10][0], s[10][1], s[10][2]);
glVertex3fv(cube[1]);
glVertex3fv(cube[2]);
glVertex3fv(cube[24]);
glVertex3fv(cube[25]);
glColor3f(s[9][0], s[9][1], s[9][2]);
glVertex3fv(cube[2]);
glVertex3fv(cube[3]);
glVertex3fv(cube[23]);
glVertex3fv(cube[24]);
glColor3f(s[12][0], s[12][1], s[12][2]);
glVertex3fv(cube[23]);
glVertex3fv(cube[24]);
glVertex3fv(cube[27]);
glVertex3fv(cube[22]);
glColor3f(s[15][0], s[15][1], s[15][2]);
glVertex3fv(cube[22]);
glVertex3fv(cube[27]);
glVertex3fv(cube[20]);
glVertex3fv(cube[21]);
glColor3f(s[16][0], s[16][1], s[16][2]);
glVertex3fv(cube[27]);
glVertex3fv(cube[26]);
glVertex3fv(cube[19]);
glVertex3fv(cube[20]);
glColor3f(s[17][0], s[17][1], s[17][2]);
glVertex3fv(cube[26]);
glVertex3fv(cube[17]);
glVertex3fv(cube[18]);
glVertex3fv(cube[19]);
glColor3f(s[14][0], s[14][1], s[14][2]);
glVertex3fv(cube[25]);
glVertex3fv(cube[16]);
glVertex3fv(cube[17]);
glVertex3fv(cube[26]);
glColor3f(s[13][0], s[13][1], s[13][2]);
glVertex3fv(cube[24]);
glVertex3fv(cube[25]);
glVertex3fv(cube[26]);
glVertex3fv(cube[27]);
// Cara 3
glColor3f(s[47][0], s[47][1], s[47][2]);
glVertex3fv(cube[18]);
glVertex3fv(cube[19]);
glVertex3fv(cube[29]);
glVertex3fv(cube[28]);
glColor3f(s[46][0], s[46][1], s[46][2]);
glVertex3fv(cube[19]);
glVertex3fv(cube[20]);
glVertex3fv(cube[30]);
glVertex3fv(cube[29]);
glColor3f(s[45][0], s[45][1], s[45][2]);
glVertex3fv(cube[20]);
glVertex3fv(cube[21]);
glVertex3fv(cube[31]);
glVertex3fv(cube[30]);
glColor3f(s[48][0], s[48][1], s[48][2]);
glVertex3fv(cube[31]);
glVertex3fv(cube[30]);
glVertex3fv(cube[39]);
glVertex3fv(cube[32]);
glColor3f(s[51][0], s[51][1], s[51][2]);
glVertex3fv(cube[32]);
glVertex3fv(cube[39]);
glVertex3fv(cube[34]);
glVertex3fv(cube[33]);
glColor3f(s[52][0], s[52][1], s[52][2]);
glVertex3fv(cube[39]);
glVertex3fv(cube[38]);
glVertex3fv(cube[35]);
glVertex3fv(cube[34]);
glColor3f(s[53][0], s[53][1], s[53][2]);
glVertex3fv(cube[38]);
glVertex3fv(cube[37]);
glVertex3fv(cube[36]);
glVertex3fv(cube[35]);
glColor3f(s[50][0], s[50][1], s[50][2]);
glVertex3fv(cube[29]);
glVertex3fv(cube[28]);
glVertex3fv(cube[37]);
glVertex3fv(cube[38]);
glColor3f(s[49][0], s[49][1], s[49][2]);
glVertex3fv(cube[30]);
glVertex3fv(cube[29]);
glVertex3fv(cube[38]);
glVertex3fv(cube[39]);
// Cara 4
glColor3f(s[33][0], s[33][1], s[33][2]);
glVertex3fv(cube[35]);
glVertex3fv(cube[36]);
glVertex3fv(cube[40]);
glVertex3fv(cube[41]);
glColor3f(s[34][0], s[34][1], s[34][2]);
glVertex3fv(cube[34]);
glVertex3fv(cube[35]);
glVertex3fv(cube[41]);
glVertex3fv(cube[42]);
glColor3f(s[35][0], s[35][1], s[35][2]);
glVertex3fv(cube[33]);
glVertex3fv(cube[34]);
glVertex3fv(cube[42]);
glVertex3fv(cube[43]);
glColor3f(s[32][0], s[32][1], s[32][2]);
glVertex3fv(cube[43]);
glVertex3fv(cube[42]);
glVertex3fv(cube[45]);
glVertex3fv(cube[44]);
glColor3f(s[29][0], s[29][1], s[29][2]);
glVertex3fv(cube[44]);
glVertex3fv(cube[45]);
glVertex3fv(cube[7]);
glVertex3fv(cube[6]);
glColor3f(s[28][0], s[28][1], s[28][2]);
glVertex3fv(cube[45]);
glVertex3fv(cube[46]);
glVertex3fv(cube[8]);
glVertex3fv(cube[7]);
glColor3f(s[27][0], s[27][1], s[27][2]);
glVertex3fv(cube[46]);
glVertex3fv(cube[47]);
glVertex3fv(cube[9]);
glVertex3fv(cube[8]);
glColor3f(s[30][0], s[30][1], s[30][2]);
glVertex3fv(cube[41]);
glVertex3fv(cube[40]);
glVertex3fv(cube[47]);
glVertex3fv(cube[46]);
glColor3f(s[31][0], s[31][1], s[31][2]);
glVertex3fv(cube[42]);
glVertex3fv(cube[41]);
glVertex3fv(cube[46]);
glVertex3fv(cube[45]);
// Cara 5
glColor3f(s[18][0], s[18][1], s[18][2]);
glVertex3fv(cube[11]);
glVertex3fv(cube[48]);
glVertex3fv(cube[16]);
glVertex3fv(cube[0]);
glColor3f(s[21][0], s[21][1], s[21][2]);
glVertex3fv(cube[48]);
glVertex3fv(cube[51]);
glVertex3fv(cube[17]);
glVertex3fv(cube[16]);
glColor3f(s[24][0], s[24][1], s[24][2]);
glVertex3fv(cube[51]);
glVertex3fv(cube[28]);
glVertex3fv(cube[18]);
glVertex3fv(cube[17]);
glColor3f(s[25][0], s[25][1], s[25][2]);
glVertex3fv(cube[50]);
glVertex3fv(cube[37]);
glVertex3fv(cube[28]);
glVertex3fv(cube[51]);
glColor3f(s[26][0], s[26][1], s[26][2]);
glVertex3fv(cube[40]);
glVertex3fv(cube[36]);
glVertex3fv(cube[37]);
glVertex3fv(cube[50]);
glColor3f(s[23][0], s[23][1], s[23][2]);
glVertex3fv(cube[47]);
glVertex3fv(cube[40]);
glVertex3fv(cube[50]);
glVertex3fv(cube[49]);
glColor3f(s[20][0], s[20][1], s[20][2]);
glVertex3fv(cube[9]);
glVertex3fv(cube[47]);
glVertex3fv(cube[49]);
glVertex3fv(cube[10]);
glColor3f(s[19][0], s[19][1], s[19][2]);
glVertex3fv(cube[10]);
glVertex3fv(cube[49]);
glVertex3fv(cube[48]);
glVertex3fv(cube[11]);
glColor3f(s[22][0], s[22][1], s[22][2]);
glVertex3fv(cube[51]);
glVertex3fv(cube[50]);
glVertex3fv(cube[49]);
glVertex3fv(cube[48]);
// Cara 6
glColor3f(s[36][0], s[36][1], s[36][2]);
glVertex3fv(cube[44]);
glVertex3fv(cube[6]);
glVertex3fv(cube[5]);
glVertex3fv(cube[53]);
glColor3f(s[39][0], s[39][1], s[39][2]);
glVertex3fv(cube[43]);
glVertex3fv(cube[44]);
glVertex3fv(cube[53]);
glVertex3fv(cube[54]);
glColor3f(s[42][0], s[42][1], s[42][2]);
glVertex3fv(cube[33]);
glVertex3fv(cube[43]);
glVertex3fv(cube[54]);
glVertex3fv(cube[32]);
glColor3f(s[43][0], s[43][1], s[43][2]);
glVertex3fv(cube[32]);
glVertex3fv(cube[54]);
glVertex3fv(cube[55]);
glVertex3fv(cube[31]);
glColor3f(s[44][0], s[44][1], s[44][2]);
glVertex3fv(cube[31]);
glVertex3fv(cube[55]);
glVertex3fv(cube[22]);
glVertex3fv(cube[21]);
glColor3f(s[41][0], s[41][1], s[41][2]);
glVertex3fv(cube[55]);
glVertex3fv(cube[52]);
glVertex3fv(cube[23]);
glVertex3fv(cube[22]);
glColor3f(s[38][0], s[38][1], s[38][2]);
glVertex3fv(cube[52]);
glVertex3fv(cube[4]);
glVertex3fv(cube[3]);
glVertex3fv(cube[23]);
glColor3f(s[37][0], s[37][1], s[37][2]);
glVertex3fv(cube[53]);
glVertex3fv(cube[5]);
glVertex3fv(cube[4]);
glVertex3fv(cube[52]);
glColor3f(s[40][0], s[40][1], s[40][2]);
glVertex3fv(cube[53]);
glVertex3fv(cube[54]);
glVertex3fv(cube[55]);
glVertex3fv(cube[52]);
glEnd();
glMatrixMode(GL_MODELVIEW);
if (mov == 1) {
glRotatef(2.0, 0, 0, 0);
}
else if (mov == 2) {
glRotatef(2.0, 1.0, 0, 0);
}
else if (mov == 3) {
glRotatef(2.0, 0, 1.0, 0);
}
else if (mov == 4) {
glRotatef(2.0, 0, 0, 1.0);
}
else
glRotatef(1.0, 0, 0, 0);
}
Rotation is going to be too hard to keep track of unless you refactor your code into some sort of "Block" class, whereby a 3x3 array of blocks will make your Rubik's cube. each block will be exactly the same: white bottom, yellow top, blue left, etc... and when stacked 3x3 on screen will hide the other faces. This is a much easier simplification than keeping track of an array of faces to an array of colors.
Then you will want to make a clear distinction between the code model of your Rubik's cube, and the drawn model of your Rubik's cube. This is important in being able to apply multiply rotations successively.
So in code you will want to have a model of your cube. a 3x3 array is easy, where each row is a face. Then looking at a face, for example:
1 2 3
4 5 6
7 8 9
you will want access to a function that rotates this face (look at something that does the equivalent as numpy.rot90), such that when rotated around the axis that is pointing out of the screen, will produce:
3 6 9
2 5 8
1 4 7
But be careful here. This only changed the layout of the object in memory and hasn't done anything to the drawn model on screen. So you will need to apply the corresponding rotation in OpenGL. After this is done, your code model will now match the drawn model, and you can perform as many successive rotations as you want.

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

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]

Initializing a global 2D array in C from a function

float verticies[14][3];
init_mod(){
verticies = {{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{ 0.5, 0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5,-0.5,-0.5},
{-0.5,-0.5, 0.5},
{-0.5, 0.5,-0.5},
{-0.5, 0.5, 0.5}};
}
When I compile the program I get this error:
topsecret.c: In function ‘init_mod’:
topsecret.c:12:14: error: expected expression before ‘{’ token
The syntax that you are using is allowed only for initialization; it is not allowed for assignments.
Moving it to the declaration of your global array will fix the problem:
float verticies[14][3] =
{{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{ 0.5, 0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5,-0.5,-0.5},
{-0.5,-0.5, 0.5},
{-0.5, 0.5,-0.5},
{-0.5, 0.5, 0.5}};
If you need to re-assign the array at some later time, you can initialize a temporary "template" array inside your function, and then use memcpy to put its content into the global array.
Since it is the 2-d array it should be declared like this data_type array_name [][]; note the you will have to pass some value for last [] bracket. i.e. `float vertices[][3] = _;
init_mod()
{
verticies [][3] = {{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{ 0.5, 0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5,-0.5,-0.5},
{-0.5,-0.5, 0.5},
{-0.5, 0.5,-0.5},
{-0.5, 0.5, 0.5}};
}
You can't directly assign arrays, so creating an array compound literal doesn't help. However, arrays inside structures can be assigned via compound literals. Therefore, you could consider using:
struct FloatArray
{
float verticies[14][3];
};
struct FloatArray vertices;
float (*verticies)[3] = vertices.verticies;
extern void init_mod(void);
void init_mod(void)
{
vertices = (struct FloatArray){
.verticies =
{
{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{ 0.5, 0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5,-0.5,-0.5},
{-0.5,-0.5, 0.5},
{-0.5, 0.5,-0.5},
{-0.5, 0.5, 0.5},
}
};
}
The code exploits your misspelling of vertices and leaves your existing code unchanged, even though the type of the global verticies has changed to a pointer to an array. The code inside the function uses a compound literal to initialize the structure, which has the (beneficial) side-effect of initializing the array pointed at by the pointer.
This code compiles cleanly under GCC 4.8.2 on Mac OS X 10.9.2 Mavericks with the command line:
gcc -g -O3 -std=c99 -Wall -Wextra -Werror -c crazy.c
I assume that the initialization function is needed to reset the array to a known state before the start of the next iteration of some code that uses and modifies the array. If you only need the array initialized once when the program starts, then you do things differently, with a simple array initializer. But it seems likely that you already know that.
And this code demonstrates the equivalence. The array old_vertices corresponds to your definition of verticies but is initialized (once).
#include <stdio.h>
float old_vertices[14][3] =
{
{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{ 0.5, 0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5,-0.5,-0.5},
{-0.5,-0.5, 0.5},
{-0.5, 0.5,-0.5},
{-0.5, 0.5, 0.5},
};
struct FloatArray
{
float verticies[14][3];
};
struct FloatArray vertices;
float (*verticies)[3] = vertices.verticies;
extern void init_mod(void);
void init_mod(void)
{
vertices = (struct FloatArray){
.verticies =
{
{-0.5,-0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5, 0.5, 0.5},
{ 0.5, 0.5, 0.5},
{-0.5, 0.5,-0.5},
{ 0.5, 0.5,-0.5},
{-0.5,-0.5,-0.5},
{ 0.5,-0.5,-0.5},
{ 0.5, 0.5, 0.5},
{ 0.5,-0.5, 0.5},
{-0.5,-0.5,-0.5},
{-0.5,-0.5, 0.5},
{-0.5, 0.5,-0.5},
{-0.5, 0.5, 0.5},
}
};
}
int main(void)
{
init_mod();
double old_sum = 0.0;
double sum = 0.0;
for (int i = 0; i < 14; i++)
{
for (int j = 0; j < 3; j++)
{
old_vertices[i][j] *= (i * 14 + j);
old_sum += old_vertices[i][j];
verticies[i][j] *= (i * 14 + j);
sum += verticies[i][j];
}
}
printf("%f == %f\n", old_sum, sum);
return 0;
}

webgl drawElements:attribs not setup correctly (repeated n times)

So, I've begun a rather instantaneous trip into the world of visual, 3-d programming. I'm currently heavily invested in webgl with a rather strong background in JavaScript and most web-oriented languages but this is my first graphics language.
While trying to draw my first rather simple shape, I've run into an error I can't seem to locate a solution for. It reads in chrome as a:
WebGL: INVALID_OPERATION: drawElements:attribs not setup correctly (repeated n times)
where n is a number that varies seemingly randomly. The code in question is here:
var tessVertexPositionBuffer;
var tessVertexColorBuffer;
var tessVertexIndexBuffer;
function initBuffers () {
tessVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexPositionBuffer);
var vertices = [
//innerfront
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
//innerleft
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
//innerback
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
//innerright
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
//topfront
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-2.0, 2.0, 2.0,
2.0, 2.0, 2.0,
//topleft
-1.0, 1.0, 1.0,
-2.0, 2.0, 2.0,
-1.0, 1.0, -1.0,
-2.0, 2.0, -2.0,
//topback
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
-2.0, 2.0, -2.0,
2.0, 2.0, -2.0,
//topright
1.0, 1.0, 1.0,
2.0, 2.0, 2.0,
1.0, 1.0, -1.0,
2.0, 2.0, -2.0,
//outerfront
-2.0, 2.0, 2.0,
2.0, 2.0, 2.0,
-2.0, -2.0, 2.0,
2.0, -2.0, 2.0,
//outerleft
-2.0, 2.0, 2.0,
-2.0, -2.0, 2.0,
-2.0, 2.0, -2.0,
-2.0, -2.0, -2.0,
//outerback
-2.0, 2.0, -2.0,
2.0, 2.0, -2.0,
-2.0, -2.0, -2.0,
2.0, -2.0, -2.0,
//outerright
2.0, 2.0, 2.0,
2.0, -2.0, 2.0,
2.0, 2.0, -2.0,
2.0, -2.0, -2.0,
//bottomfront
2.0, 2.0, 2.0,
-2.0, 2.0, 2.0,
-2.0, -2.0, 2.0,
2.0, -2.0, 2.0,
//bottomleft
-1.0, -1.0, 1.0,
-2.0, -2.0, 2.0,
-1.0, -1.0, -1.0,
-2.0, -2.0, -2.0,
//bottomback
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
-2.0, -2.0, -2.0,
2.0, -2.0, -2.0,
//bottomright
1.0, -1.0, 1.0,
2.0, -2.0, 2.0,
1.0, -1.0, -1.0,
2.0, -2.0, -2.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
tessVertexPositionBuffer.itemSize = 3;
tessVertexPositionBuffer.numItems = 64;
tessVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexColorBuffer);
var colors = [
[0.7, 0.7, 0.7, 1.0], //all inner sides
[0.7, 0.7, 0.7, 1.0],
[0.7, 0.7, 0.7, 1.0],
[0.7, 0.7, 0.7, 1.0],
[0.7, 0.0, 0.7, 1.0], //all top sides
[0.7, 0.0, 0.7, 1.0],
[0.7, 0.0, 0.7, 1.0],
[0.7, 0.0, 0.7, 1.0],
[0.7, 0.7, 0.0, 1.0], //all outer sides
[0.7, 0.7, 0.0, 1.0],
[0.7, 0.7, 0.0, 1.0],
[0.7, 0.7, 0.0, 1.0],
[0.0, 0.7, 0.7, 1.0], //all bottom sides
[0.0, 0.7, 0.7, 1.0],
[0.0, 0.7, 0.7, 1.0],
[0.0, 0.7, 0.7, 1.0],
];
var unpackedColors = [];
for (var i in colors) {
var color = colors[i];
for (var j=0; j< 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(unpackedColors), gl.STATIC_DRAW);
tessVertexColorBuffer.itemSize = 4;
tessVertexColorBuffer.numItems = 64;
tessVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tessVertexIndexBuffer);
var tessVertexIndices = [
0, 1, 2, 0, 2, 3,
4, 5, 6, 5, 6, 7,
8, 9, 10, 9, 10, 11,
12, 13, 14, 13, 14, 15,
16, 17, 18, 17, 18, 19,
20, 21, 22, 21, 22, 23,
24, 25, 26, 25, 26, 27,
28, 29, 30, 29, 30, 31,
32, 33, 34, 33, 34, 35,
36, 37, 38, 37, 38, 39,
40, 41, 42, 41, 42, 43,
44, 45, 46, 45, 46, 47,
48, 49, 50, 48, 50, 51,
52, 53, 54, 53, 54, 55,
56, 57, 58, 57, 58, 59,
60, 61, 62, 61, 62, 63
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(tessVertexIndices), gl.STATIC_DRAW);
tessVertexIndexBuffer.itemSize = 1;
tessVertexIndexBuffer.numItems = 96;
}
and the actual drawing of the buffers is here:
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vetexPositionAttribute, tessVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, tessVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, tessVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, tessVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, tessVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
Now, this is relatively verbatim from learningwebgl, I'm really just trying to draw a simple shape. I'm relatively certain that my problem lies in my buffer types because I honestly don't uderstand much about them (and most literature on webGl I've found is either novice with a general understanding of the language or of the HYPERSUPERPRO variety).
I've checked over the actual vertex positions/colors/indices multiple times and unless I've just become familiar with the code enough that I'm blind to the simple errors, I can't find an error there.
Looks like your problem is just a small typo. The second line of your "actual drawing of buffers" code should be he following:
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, tessVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
You were missing the first r in vertexPositionAttribute on that line.
I modified the lesson 4 LearningWebGL tutorial to use your code (with the fixed typo) and I have a link to it here.
If you notice there is a blue triangle and a yellow triangle being drawn at the exact same position in space which causes some flickering. I'm not sure if that was intentional.

Resources