I have a particle system and I am using boost::geometry to approximate my elliptical particles as polygons and then use the intersection function of the library to find the overlap area. I am calculating an "inner" and "outer" ellipse(polygon) area to assign a "potential" for each particle-particle interaction.
My potential function is this:
double Potential(Cell* current, Cell* next)
{
double areaRep, areaAtt;
double distance = Distance(current,next);
double A1 = current->getLength();
double B1 = A1/2.0;
double theta1 = current->getTheta(); //*180.0/M_PI
double x1 = current->getCurrX();
double y1 = current->getCurrY();
double A2 = next->getLength();
double B2 = A2/2.0;
double theta2 = next->getTheta();
double x2 = next->getCurrX();
double y2 = next->getCurrY();
polygon_2d poly1, poly2, poly3, poly4;
double lamda1, lamda2;
lamda1 = 0.0005; lamda2 = 0.00001;
if(distance < 2.0*1.5*A1) {
ellipse2poly(theta1, A1, B1, x1, y1, &poly1);
ellipse2poly(theta2, A2, B2, x2, y2, &poly2);
areaRep = getOverlapingAreaPoly(poly1,poly2);
ellipse2poly(theta1, 1.5*A1, 1.5*B1, x1, y1, &poly3);
ellipse2poly(theta2, 1.5*A2, 1.5*B2, x2, y2, &poly4);
areaAtt = getOverlapingAreaPoly(poly3, poly4);
return (lamda1*areaRep - lamda2*areaAtt);
}
else
return 0.0;
}
The "polygonizing" function is:
int ellipse2poly(double theta, double A1, double B1, double H1, double K1, polygon_2d *po)
{
using namespace boost::geometry;
polygon_2d poly;
const int n = 20;
double angle = theta; // cell orientation
double a = A1; // Long semi-axis length
double b = B1; // short semi-axis length
double xc = H1; // current X position
double yc = K1; // current Y position
if(!n)
{
std::cout << "error ellipse(): n should be >0\n" <<std::endl;
return 0;
}
double t = 0;
int i = 0;
double coor[2*n+1][2];
double x, y;
double step = M_PI/(double)n;
double sinphi = sin(angle);
double cosphi = cos(angle);
for(i=0; i<2*n+1; i++)
{
x = xc + a*cos(t)*cosphi - b*sin(t)*sinphi;
y = yc + a*cos(t)*sinphi + b*sin(t)*cosphi;
coor[i][0] = x;
coor[i][1] = y;
t += step;
}
assign_points(poly, coor);
correct(poly);
*po = poly;
return 1;
}
And the returned area is:
double getOverlapingAreaPoly(polygon_2d poly, polygon_2d poly2)
{
point_2d cent; //centre of overlaping area
double overAreaPoly = 0.0;
typedef std::vector<polygon_2d > polygon_list;
polygon_list v;
intersection(poly,poly2,v);
for (polygon_list::const_iterator it = v.begin(); it != v.end(); ++it)
{
centroid(*it, cent);
overAreaPoly = area(*it);
}
return overAreaPoly;
}
The function is called for every cell (particle) as long as it is not for the same one. Previously, using another method, one iteration of my algorithm would take approximately 43 ms for one iteration for 100 particles. Now it takes approximately 1 min(!!!), so I guess I have done something horribly wrong!
I have tested this only in MSVC2012 under win7 64bit. I will report back for Linux Mint with Qt 4.7.4.
EDIT:
I have tested on Linux Mint with Qt 4.7.4 and it is running very reasonably; maybe 90-100 ms per iteration which is fine. I don't know what is wrong in win7...
I have actually fixed it. I started a new project in Visual Studio and copied all source and header files, recompiled and everything runs smoothly now. I guess radically changing code and adding / subtracting stuff must have some impact...
Related
I'm new in the world of C++ and I'm having some trouble with the boost library. In my problem I want to solve a ODE-System with 5 equations. It isn't a stiff problem. As iterative method I used both integreate(rhs, x0, t0, tf, size_step, write_output) and integreate_adaptive(stepper, sys, x0, t0, tf, size_step, write_output). Both these method actually integrate the equations but giving me non-sense results changing the size of the step from 0.001 to 5 almost randomly. The equations and data are correct. What can I do to fix this problem? Here is the code:
#include <iostream>
#include <vector>
#include <boost/numeric/odeint.hpp>
#include <fstream>
#include <boost/array.hpp>
using namespace std;
using namespace boost::numeric::odeint;
//DATA
double Lin = 20000; // kg/h
double Gdry = 15000; // kg/h
double P = 760; // mmHg
double TinH2O = 50; // °C
double ToutH2O = 25; // °C
double Tinair = 20; // °C
double Z = 0.5; // relative humidity
double Cu = 0.26; // kcal/kg*K
double CpL = 1; // kcal/kg*K
double DHev = 580; // kcal/kg
double hga = 4000; // kcal/m/h/K
double hla = 30000; // kcal/m/h/K
double A = -49.705; // Pev 1st coeff mmHg vs °C
double B = 2.71; // Pev 2nd coeff mmHg vs °C
double Usair = 0.62*(A + B*Tinair) / P;
double Uair = Z*Usair;
double Kua = hga / Cu;
double L0 = 19292; // kg/h
typedef vector< double > state_type;
vector <double> pack_height;
vector <double> Umidity;
vector <double> T_liquid;
vector <double> T_gas;
vector <double> Liquid_flow;
vector <double> Gas_flow;
void rhs(const state_type& x , state_type& dxdt , const double z )
{// U Tl Tg L G
double Ti = (hla*x[1] + hga*x[2] + Kua*DHev*(x[0] - 0.62*A / P)) / (hla + hga + Kua*DHev*0.62*B / P);
double Ui = 0.62*(A + B*Ti) / P;
dxdt[0] = Kua*(Ui - x[0]) / Gdry / 100;
dxdt[1] = hla*(x[1] - Ti) / x[3] / CpL / 100;
dxdt[2] = hga*(Ti - x[2]) / Gdry / Cu / 100;
dxdt[3] = Kua*(Ui - x[0]) / 100;
dxdt[4] = Kua*(Ui - x[0]) / 100;
}
void write_output(const state_type& x, const double z)
{
pack_height.push_back(z);
Umidity.push_back(x[0]);
T_liquid.push_back(x[1]);
T_gas.push_back(x[2]);
Liquid_flow.push_back(x[3]);
Gas_flow.push_back(x[4]);
cout << z << " " << x[0] << " " << x[1] << " " << x[2] << " " << x[3] << " " << x[4] << endl;
}
int main()
{
state_type x(5);
x[0] = Uair;
x[1] = ToutH2O;
x[2] = Tinair;
x[3] = L0;
x[4] = Gdry;
double z0 = 0.0;
double zf = 5.5;
double stepsize = 0.001;
integrate( rhs , x , z0 , zf , stepsize , write_output );
return 0;
}
And this is the final results that i get from the prompt:
0 0.00183349 25 20 19292 15000
0.001 0.00183356 25 20 19292 15000
0.0055 0.0018339 25.0002 20.0001 19292 15000
0.02575 0.00183542 25.001 20.0007 19292 15000
0.116875 0.00184228 25.0046 20.003 19292.1 15000.1
0.526938 0.00187312 25.0206 20.0135 19292.6 15000.6
2.37222 0.00201203 25.0928 20.0608 19294.7 15002.7
5.5 0.00224788 25.2155 20.142 19298.2 15006.2
Only the first iteration has the right-asked stepsize.. and obiviously the solution is not the right one.. what can i do? Thank you in advance. :)
If you read the documentation, then you will find that the constant step-size routines are integrate_const and integrate_n_steps, or possibly integrate_adaptive with a non-controlled stepper.
The short call to integrate uses the standard dopri5 stepper with adaptive step size, so that the changing step size is no surprise. You could possibly use the dense output of the stepper to interpolate values at equidistant times.
I'm using CppAD with Ipopt. In some places I have to typecast the AD format to its base format that is double. I have used CppAD::Value(AD var) it gives me output in double format.
But considering line no.27 the code is fine during compile time. Its showing the following error in runtime. The error is :
cppad-20160000.1 error from a known source:
Value: argument is a variable (not a parameter)
Error detected by false result for
Parameter(x)
at line 89 in the file
/usr/include/cppad/local/value.hpp
I have attached the code I'm running for verification. Kindly help. please install Ipopt before running the code.
The type of value is still CppAD::AD . But the Value() is not working.
#include <cppad/ipopt/solve.hpp>
#include <iostream>
namespace {
using CppAD::AD;
class FG_eval {
public:
typedef CPPAD_TESTVECTOR( AD<double> ) ADvector;
void operator()(ADvector& fg, const ADvector& x)
{ assert( fg.size() == 3 );
assert( x.size() == 4 );
// Fortran style indexing
AD<double> x1 = x[0];
AD<double> x2 = x[1];
AD<double> x3 = x[2];
AD<double> x4 = x[3];
// f(x)
fg[0] = x1 * x4 * (x1 + x2 + x3) + x3;
// g_1 (x)
fg[1] = x1 * x2 * x3 * x4;
// g_2 (x)
fg[2] = x1 * x1 + x2 * x2 + x3 * x3 + x4 * x4;
// help on this line
std::cout << CppAD::Value(x1) << std::endl;
//
return;
}
};
}
bool get_started()
{ bool ok = true;
size_t i;
typedef CPPAD_TESTVECTOR( double ) Dvector;
// number of independent variables (domain dimension for f and g)
size_t nx = 4;
// number of constraints (range dimension for g)
size_t ng = 2;
// initial value of the independent variables
Dvector xi(nx);
xi[0] = 1.0;
xi[1] = 5.0;
xi[2] = 5.0;
xi[3] = 1.0;
// lower and upper limits for x
Dvector xl(nx), xu(nx);
for(i = 0; i < nx; i++)
{ xl[i] = 1.0;
xu[i] = 5.0;
}
// lower and upper limits for g
Dvector gl(ng), gu(ng);
gl[0] = 25.0; gu[0] = 1.0e19;
gl[1] = 40.0; gu[1] = 40.0;
// object that computes objective and constraints
FG_eval fg_eval;
// options
std::string options;
// turn off any printing
options += "Integer print_level 0\n";
options += "String sb yes\n";
// maximum number of iterations
options += "Integer max_iter 10\n";
// approximate accuracy in first order necessary conditions;
// see Mathematical Programming, Volume 106, Number 1,
// Pages 25-57, Equation (6)
options += "Numeric tol 1e-6\n";
// derivative testing
options += "String derivative_test second-order\n";
// maximum amount of random pertubation; e.g.,
// when evaluation finite diff
options += "Numeric point_perturbation_radius 0.\n";
// place to return solution
CppAD::ipopt::solve_result<Dvector> solution;
// solve the problem
CppAD::ipopt::solve<Dvector, FG_eval>(
options, xi, xl, xu, gl, gu, fg_eval, solution
);
//
// Check some of the solution values
//
ok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;
//
double check_x[] = { 1.000000, 4.743000, 3.82115, 1.379408 };
double check_zl[] = { 1.087871, 0., 0., 0. };
double check_zu[] = { 0., 0., 0., 0. };
double rel_tol = 1e-6; // relative tolerance
double abs_tol = 1e-6; // absolute tolerance
for(i = 0; i < nx; i++)
{ ok &= CppAD::NearEqual(
check_x[i], solution.x[i], rel_tol, abs_tol
);
ok &= CppAD::NearEqual(
check_zl[i], solution.zl[i], rel_tol, abs_tol
);
ok &= CppAD::NearEqual(
check_zu[i], solution.zu[i], rel_tol, abs_tol
);
}
return ok;
}
int main()
{
get_started();
return 0;
}
cmakelists.txt
cmake_minimum_required(VERSION 3.5)
project(jnk)
add_compile_options(-std=c++11)
add_executable(${PROJECT_NAME} testCppAD.cpp)
target_link_libraries(${PROJECT_NAME}
ipopt z uv
)
I found out the answer. We have to use an inbuilt function CppAD::Var2Par() before using CppAD::Value(). Will work.
I am currently working on a 3D Perlin noise implementation in C++, and there are strange block-like artifacts when I visualize it as a video of 2D slices through the 3D volume as defined by this code with just one octave:
#include <png++/png.hpp>
#include <memory>
#include <string>
#include "Octave.h"
constexpr unsigned IMAGE_SIZE = 512;
std::string numberToString(unsigned n, unsigned digits);
int main() {
std::mt19937_64 rnd(0);
auto octave = std::make_unique<Octave>(&rnd, 32, 1); //make_unique because Octave objects are too big to fit on the stack
for(unsigned z=0;z<625;++z){
std::cout << z << "/625" << std::endl;
png::image<png::rgb_pixel> image(IMAGE_SIZE, IMAGE_SIZE);
for(unsigned x=0;x<IMAGE_SIZE;++x){
for(unsigned y=0;y<IMAGE_SIZE;++y){
unsigned brightness = (octave->noise(x, z*(64.0/300.0), y)*.5+.5)*255;
image[y][x] = png::rgb_pixel(brightness, brightness, brightness);
}
}
image.write("output/perlin-" + numberToString(z, 4) + ".png");
}
return 0;
}
std::string numberToString(unsigned n, unsigned digits){
std::string string = std::to_string(n);
while(string.length() < digits){
string = "0" + string;
}
return string;
}
Each image from the above program is a single frame in a video. A video showing the output of this problem (converted to a video via ffmpeg) is available here: https://youtu.be/f7NxYo8U7TQ. Youtube added some compression artifacts in that video that are not present in the program's output.
As is clear in the above video, as the slice moves along the Z axis, square artifacts are present: . Depending on which plane slices are made in (eg. XZ or ZY), the artifacts slightly change in nature. It appears that they are worse just after a roll over in the frequency of the one rendered octave.
What is the cause of this?
Octave.h:
#pragma once
#include <array>
#include <random>
class Octave{
public:
Octave(std::mt19937_64 *rnd, double frequency, double amplitude);
double noise(double x, double y, double z);
private:
static constexpr int PERMUTATION_TABLE_PART_SIZE = 1000000;
static constexpr int PERMUTATION_TABLE_PART_COUNT = 3;
static constexpr int PERMUTATION_TABLE_SIZE = PERMUTATION_TABLE_PART_SIZE*PERMUTATION_TABLE_PART_COUNT;
std::array<int, PERMUTATION_TABLE_SIZE> m_permutationTable;
double m_frequency, m_amplitude;
double influence(int x, int y, int z, double distanceX, double distanceY, double distanceZ);
inline static double square(double d) { return d*d; }
inline static double vectorLength(double x, double y, double z);
inline static double interpolate(double a, double b, double x);
};
Octave.cpp:
#include "Octave.h"
#include <utility>
#include <cmath>
#include <iostream>
Octave::Octave(std::mt19937_64 *rnd, double frequency, double amplitude) : m_frequency(frequency), m_amplitude(amplitude) {
//fill in basic array
for(int i=0;i<PERMUTATION_TABLE_PART_SIZE;++i){
for(int j=0;j<PERMUTATION_TABLE_PART_COUNT;++j){
m_permutationTable[i+PERMUTATION_TABLE_PART_SIZE*j] = i;
}
}
//shuffle array
for(int i=0;i<PERMUTATION_TABLE_SIZE;++i){
int swapWith = ((*rnd)() % (PERMUTATION_TABLE_SIZE-i))+i;
std::swap(m_permutationTable[i], m_permutationTable[swapWith]);
}
}
double Octave::noise(double x, double y, double z) {
x /= m_frequency;
y /= m_frequency;
z /= m_frequency;
int intX = std::floor(x);
int intY = std::floor(y);
int intZ = std::floor(z);
double floatX = x - intX;
double floatY = y - intY;
double floatZ = z - intZ;
double influence1 = influence(intX, intY, intZ, floatX, floatY, floatZ);
double influence2 = influence(intX+1, intY, intZ, floatX-1, floatY, floatZ);
double influence3 = influence(intX+1, intY+1, intZ, floatX-1, floatY-1, floatZ);
double influence4 = influence(intX, intY+1, intZ, floatX, floatY-1, floatZ);
double influence5 = influence(intX, intY, intZ+1, floatX, floatY, floatZ-1);
double influence6 = influence(intX+1, intY, intZ+1, floatX-1, floatY, floatZ);
double influence7 = influence(intX+1, intY+1, intZ+1, floatX-1, floatY-1, floatZ-1);
double influence8 = influence(intX, intY+1, intZ+1, floatX, floatY-1, floatZ-1);
double frontUpperInterpolatedValue = interpolate(influence4, influence3, floatX);
double backUpperInterpolatedValue = interpolate(influence8, influence7, floatX);
double frontLowerInterpolatedValue = interpolate(influence1, influence2, floatX);
double backLowerInterpolatedValue = interpolate(influence5, influence6, floatX);
double upperInterpolatedValue = interpolate(frontUpperInterpolatedValue, backUpperInterpolatedValue, floatZ);
double lowerInterpolatedValue = interpolate(frontLowerInterpolatedValue, backLowerInterpolatedValue, floatZ);
return interpolate(lowerInterpolatedValue, upperInterpolatedValue, floatY)*m_amplitude;
}
double Octave::influence(int x, int y, int z, double distanceX, double distanceY, double distanceZ) {
//create un-normalized gradient vector
//the ordering of x, y, and z is arbitrary but different to produce different x y and z
double gradientX = (m_permutationTable[m_permutationTable[m_permutationTable[x]+y]+z]/static_cast<double>(PERMUTATION_TABLE_PART_SIZE))*2-1;
double gradientY = (m_permutationTable[m_permutationTable[m_permutationTable[y]+x]+z]/static_cast<double>(PERMUTATION_TABLE_PART_SIZE))*2-1;
double gradientZ = (m_permutationTable[m_permutationTable[m_permutationTable[y]+x]+z]/static_cast<double>(PERMUTATION_TABLE_PART_SIZE))*2-1;
//normalize gradient vector
double gradientVectorInverseLength = 1/vectorLength(gradientX, gradientY, gradientZ);
gradientX *= gradientVectorInverseLength;
gradientY *= gradientVectorInverseLength;
gradientZ *= gradientVectorInverseLength;
//compute dot product
double dot = gradientX*distanceX+gradientY*distanceY+gradientZ*distanceZ;
return dot;
}
double Octave::vectorLength(double x, double y, double z) {
return std::sqrt(square(x)+square(y)+square(z));
}
double Octave::interpolate(double a, double b, double x) {
return (b-a)*(6*x*x*x*x*x-15*x*x*x*x+10*x*x*x)+a;
}
I determined the issue. I forgot to do floatZ-1 when calculating influence6.
I am using Rcpp to speed up a double for loop in R. I've implemented the C++ code as follows; however, regardless of the kind of input -- e.g. any kind of vectors or numbers -- I put in the function, I end up always receiving 0 as the result.
Where I did wrong in my code?
#include<Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double likelihood(NumericVector pA, NumericVector pB,
NumericVector pA_bin, NumericVector pB_bin,
double x_A, double x_B, double t_l)
{
int nrow = pA.size();
int ncol = pB.size();
int nvec = nrow*(nrow-1)/2;
int kk = 0;
NumericVector p_l_nu_vec(nvec);
//define 4 double variables to store coordinates of 4 vertices of each element
double x1 = 0;
double x2 = 0;
double y1 = 0;
double y2 = 0;
//define 4 variables to store likelihood function values at 4 vertices
double f1 = 0; //point 1, bottom-left, (x1,y1)
double f2 = 0; //point 2, bottom-right, (x2,y1)
double f3 = 0; //point 3, top-right, (x2,y2)
double f4 = 0; //point 4, top-left, (x1,y2)
for (int j=0;j<ncol;++j){
for (int i=0;i<nrow;++i){
if (i>j){
// trapzoid rule, taking average of 4 vertices of the triangular
x1 = pA_bin[i]; //x value of left, point 1,4
x2 = pA_bin[i+1]; //x value of right, point 2,3
y1 = pB_bin[j]; //y value of bottom, point 1,2
y2 = pB_bin[j+1]; //y value of top, point 3,4
f1 = pow(1-x1,t_l-x_A)*pow(x1-y1,x_A-x_B)*pow(y1,x_B);
f2 = pow(1-x2,t_l-x_A)*pow(x2-y1,x_A-x_B)*pow(y1,x_B);
f3 = pow(1-x2,t_l-x_A)*pow(x2-y2,x_A-x_B)*pow(y2,x_B);
f4 = pow(1-x1,t_l-x_A)*pow(x1-y2,x_A-x_B)*pow(y2,x_B);
//take the average of 4 vertices
p_l_nu_vec[kk] = 1/4*(f1+f2+f3+f4);
kk = kk+1;
}
}
}
//return p_l_nu_vec;
return kk;
}
Sample call in R:
p_l_nu_vec_trapzoid = likelihood(pA,pB,pA_bin,pB_bin,x_A,x_B,t_l)
Expected results should output some real numbers instead of being 0 all the time. For example, in this case, output kk records the number of iterations.
I have programmed the Graham's algorithm but it still gives me the wrong points for the convex hull. I need help. Think I have a bug in my sign function but dunno what it is.
#include <cstdio>
#include <algorithm>
#include <math.h>
#define pb push_back
#define mp make_pair
#include <vector>
using namespace std;
vector <pair<double, double> > st;
pair<double, double> p[1000];
double x, y;
int f(pair <double,double> a, pair<double, double> b)
{
double x1 = x - a.first, x2 = x - b.first;
double y1 = y - a.second, y2 = y - b.second;
return ((x1*y2-y1*x2) < 0);
}
void setlast(double &x1, double &y1, double &x2, double &y2)
{
x2 = st[st.size()-1].first;
y2 = st[st.size()-1].second;
x1 = st[st.size()-2].first;
y1 = st[st.size()-2].second;
}
sign improved I use doubles
double sign(double x1,double y1, double x2,double y2, double y3,double x3)
{
double xx1 = x2 - x1, xx2 = x3 - x1;
double yy1 = y2 - y1, yy2 = y3 - y1;
return (xx1*yy2-yy1*xx2);
}
int main()
{
int n;
x = 0x3f3f3f3f;
y = 0x3f3f3f3f;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%lf %lf", &p[i].first, &p[i].second);
if(p[i].first <= x && p[i].second <= y)
x = p[i].first,
y = p[i].second;
}
sort(p, p + n, f);
p[n].first = x;
p[n].second = y;
st.pb(mp(p[0].first, p[0].second));
st.pb(mp(p[1].first, p[1].second));
double x1, x2, x3, y1, y2, y3;
here I iterate through all vectors and try to determine the points of convex hull
for(int i = 2; i < n; i++)
{
x3 = p[i].first;
y3 = p[i].second;
setlast(x1,y1,x2,y2);
while(1)
if(sign(x1,y1,x2,y2,x3,y3) < 0)
{
st.pb(mp(x3, y3));
break;
}
else
st.pop_back(),
setlast(x1, y1, x2, y2);
}
here printing the convex hull
for(int i = 0; i < st.size(); i++)
printf("%lf %lf\n", st[i].first, st[i].second);
return 0
}
My question, why does int f(pair<int, int>, pair<int, int>) take pair<int, int> instead of pair<double, double>?
Also, why isn't it named something informative like compare_blah?
Lastly, why doesn't it return bool instead of an int? Either works of course, but it will be clearer that this is intended simply as a comparison function if you return a bool. And making your program clear to people who read it should be your primary goal. Getting it to do what it's supposed to is a secondary goal. After all, it doing what it's supposed to is only a transitory state of affairs. Eventually someone will want it to do something else.
The pair<int, int> thing could be your problem right there. You are doing several implicit type conversions in that function between int and double and losing information left and right. I doubt that's what you intended.
If you would use a typedef for your pair like typedef pair<double, double> point2d_t and then use point2d_t everywhere you could protect yourself from mistakes like that and make your program clearer in the bargain.
I'm not familiar enough with Graham's algorithm to evaluate your use of abs inside of f, though it's quite possible the person who commented on this is correct.