In order to integrate a two dimensional function of the form
$$\int_{1}^\infty \int_{-\sqrt{x^2-1}}^{\sqrt{x^2-1}} e^{-x} \rm{d}y \rm{d}x,$$
I have been attempting to use the following code (written in C++) taken mostly from the Numerical Recipes book which calls a gaussian quadrature routine for the integration:
static float xsav;
static float (*nrfunc)(float,float);
float quad2d(float (*func)(float, float), float x1, float x2)
{
float qgaus(float (*func)(float), float a, float b);
float f1(float x);
nrfunc=func;
return qgaus(f1,x1,x2);
}
float f1(float x)
{
float qgaus(float (*func)(float), float a, float b);
float f2(float y);
float yy1(float),yy2(float);
xsav=x;
return qgaus(f2,yy1(x),yy2(x));
}
float f2(float y)
{
return (*nrfunc)(xsav,y);
}
This code works fine for two dimensional integrals with finite limits, but fails as the outer limit is taken to infinity. To account for this, I have attempted to use a change of variables:
#define FUNC(x) ((*funk)(-log(x))/(x))
float qgaus(float (*funk)(float), float aa, float bb)
{
int j;
float xr,xm,dx,s,a,b;
b=exp(-aa);
a=0.0;
static float x[]={0.0,0.1488743389,0.4333953941,
0.6794095682,0.8650633666,0.9739065285};
static float w[]={0.0,0.2955242247,0.2692667193,
0.2190863625,0.1494513491,0.0666713443};
xm=0.5*(b+a);
xr=0.5*(b-a);
s=0;
for (j=1;j<=5;j++)
{
dx=xr*x[j];
s += w[j]*(FUNC(xm+dx)+FUNC(xm-dx));
}
return s *= xr;
}
float f(float x, float y)
{
float a = exp(-x);
return a;
}
float yy1(float x)
{
float y = -sqrt(x*x-1);
return y;
}
float yy2(float x)
{
float y = sqrt(x*x-1);
return y;
}
static float xsav;
static float (*nrfunc)(float, float);
float quad2d(float (*func)(float, float), float x1, float x2)
{
float qgaus(float (*func)(float), float aa, float bb);
float f1(float x);
nrfunc=func;
float t = qgaus(f1,x1,x2);
return t;
}
float f1(float x)
{
float qgaus(float (*func)(float), float aa, float bb);
float f2(float y);
float yy1(float);
float yy2(float);
xsav=x;
float r = qgaus(f2,yy1(x),yy2(x));
return r;
}
float f2(float y)
{
float k = (*nrfunc)(xsav,y);
return k;
}
int main ()
{
float z;
z = quad2d(f, 1.0, 20.0);
cout << z << endl;
}
but this still doesn't give the right answer. It should be
$2 \times \rm{BesselK}[1,1] \approx 1.20381$
but instead gives
2.15501
Any suggestions on how I could modify this code to account for the infinite limit would be greatly appreciated!
Related
My objective is to parallelise a one-dimensional integral. I have looked around, and I would say that I could do that in two ways: i) implementing OpenMP with ODEINT, boost library integrate_adapative function (see https://www.boost.org/doc/libs/1_56_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/tutorial/parallel_computation_with_openmp_and_mpi.html).; ii) implementing OpenMP with GSL monte carlo integration (as in here: Internal compiler error with nested functions in OpenMP parallel regions).
My problem is that I cannot really understand what they did in both links I provided.
I was wondering whether someone has experience with that, and may point out how I could implement both approaches on my case. Is it OpenMP with boost faster or GSL and OpenMP implementation?
PDFfunction represents the probability density function that is used within the integrand function. PDFfunction is equivalent to , and in LateX is expressed as:
And this is how I code it:
double PDFfunction(double invL, int t, double invtau, double x0, double x, int n) {
const double c = M_PI * (M_PI/4) * ((2 * t) * invtau);
double res = 0;
for(int i = 1; i <= n; ++n){
res += exp(-1 * (i * i) * c) * cos((i * M_PI * x) * invL) * cos((i * M_PI * x0) * invL);
}
return invL + ((2 * invL) * res);
}
Composite_at_t is a function that makes use of the PDFfunction to compute pbA and pbB. Composite_at_t is equivalent to , where ) and ).
double Composite_at_t(double t, double B, double x0, double xt_pos, double y0, double yt_pos, double invLtot, double invtau, int n_lim) {
double pbA = PDFfunction(invLtot, t, invtau, x0, xt_pos, n_lim);
double pbB = PDFfunction(invLtot, t, invtau, y0, yt_pos, n_lim);
double b1 = 2 * (2 * t) * exp(-2 * t * B);
return pbA * pbB * b1;
}
Composite_at_tCLASS is a Func class which computes a first integral over variable t.
class Composite_at_tCLASS: public Func{
private:
double B;
double x0;
double xt_pos;
double y0;
double yt_pos;
double invLtot;
double invtau;
int n_lim;
public:
Composite_at_tCLASS(double B_, double x0_, double xt_pos_, double y0_, double yt_pos_, double invLtot_, double invtau_, int n_lim_) : B(B_), x0(x0_), xt_pos(xt_pos_), y0(y0_), yt_pos(yt_pos_), invLtot(invLtot_), invtau(invtau_), n_lim(n_lim_) {}
double operator()(const double& t) const{
return Composite_at_t(t, B, x0, xt_pos, y0, yt_pos, invLtot, invtau, n_lim);
}
};
integrate_CompositeCLASS is the actual function that uses the class Composite_at_tCLASS and perform the integral over t, between 0 and time_lim.
double integrate_CompositeCLASS(double B, double x0, double xt_pos, double y0, double yt_pos, double invLtot, double invtau, int n_lim, double time_lim){
Composite_at_tCLASS f(B, x0, xt_pos, y0, yt_pos, invLtot, invtau, n_lim);
double err_est;
int err_code;
double res = integrate(f, 0, time_lim, err_est, err_code);
return res;
}
For the numerical integration using the GSL library I would use the following code:
struct my_f_params { double B; double x0; double xt_pos; double y0; double yt_pos; double invtau; int n_lim; double invLtot;};
double g(double *k, size_t dim, void *p){
struct my_f_params * fp = (struct my_f_params *)p;
return Composite_at_t(k[0],fp->B, fp->x0, fp->xt_pos, fp->y0, fp->yt_pos, fp->invLtot, fp->invtau, fp->n_lim);
}
And this is the actual object that perform the GSL integral:
double integrate_integral(const double& invtau, const int& n_lim, const double& invLtot,
const double& x0, const double& xt_pos, const double& y0, const double& yt_pos, const double& time_lim){
double res, err;
double xl[1] = {0};
double xu[1] = {time_lim};
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
struct my_f_params params = { B, x0, xt_pos, y0, yt_pos, invtau, n_lim, invLtot};
G.f = &g;
G.dim = 1;
G.params = ¶ms;
size_t calls = 10000;
gsl_rng_env_setup ();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
gsl_monte_vegas_state *s = gsl_monte_vegas_alloc (1);
gsl_monte_vegas_integrate (&G, xl, xu, 1, 10000, r, s,
&res, &err);
do
{
gsl_monte_vegas_integrate (&G, xl, xu, 1, calls/5, r, s,
&res, &err);
}
while (fabs (gsl_monte_vegas_chisq (s) - 1.0) > 0.5);
gsl_monte_vegas_free (s);
gsl_rng_free (r);
return res;
}
I'm trying to write a class for the UnitVector, having already written the one for a generic Vector. The UnitVector class diverges from the Vector class only by the fact that the abs variable is set to 1.0f. I'd like to know what the best approach to the problem would be, whether it's better to make another class, UnitVector, that inherits the Vector class (my current idea, that's giving me problems) or to just write a method in the Vector class
Here's my code for the class Vector:
Vector.h
class Vector
{
public:
Vector();
Vector(float x, float y);
void set_by_angle(float abs, float angle);
void set(float x, float y);
void rotate(float angle);
void scale(float scale_factor);
void translate(float x, float y);
void translate(Vector v);
float get_abs();
float get_angle();
static Vector create_by_angle(float abs, float angle);
static Vector create(float x, float y);
static Vector create_from_vectors(Vector v1, Vector v2, float abs);
static float get_distance(Vector v1, Vector v2);
static float get_angle(float x, float y);
static float get_angle(Vector v);
void to_string();
Vector operator=(const Vector &v);
bool operator==(const Vector &v);
bool operator!=(const Vector &v);
Vector operator+=(const Vector &v);
friend Vector operator+(const Vector &v1, const Vector &v2);
friend Vector operator-(const Vector &v1, const Vector &v2);
float x;
float y;
private:
float abs;
float angle;
};
Vector.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include <iostream>
#include <string>
#include "vector.h"
using namespace std;
Vector::Vector() : Vector(0, 0) {}
Vector::Vector(float x, float y)
{
set(x, y);
}
void Vector::set_by_angle(float abs, float angle)
{
this->abs = abs;
this->angle = angle;
x = abs * cos(angle);
y = abs * sin(angle);
}
void Vector::set(float x, float y)
{
this->x = x;
this->y = y;
abs = get_abs();
angle = get_angle();
}
void Vector::rotate(float angle)
{
set_by_angle(this->abs, this->angle + angle);
}
void Vector::scale(float scale_factor)
{
set(x * scale_factor, y * scale_factor);
}
void Vector::translate(float x, float y)
{
set(this->x + x, this->y + y);
}
void Vector::translate(Vector v)
{
translate(v.x, v.y);
}
float Vector::get_abs()
{
return sqrt(pow(x, 2) + pow(y, 2));
}
float Vector::get_angle()
{
return get_angle(x, y);
}
Vector Vector::create_by_angle(float abs, float angle)
{
Vector v;
v.set_by_angle(abs, angle);
return v;
}
Vector Vector::create(float x, float y)
{
Vector v;
v.set(x, y);
return v;
}
float Vector::get_distance(Vector v1, Vector v2)
{
return sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2));
}
Vector Vector::create_from_vectors(Vector v1, Vector v2, float abs)
{
float x = v2.x - v1.x;
float y = v2.y - v1.y;
Vector v;
v.set_by_angle(abs, Vector(x, y).get_angle());
return v;
}
float Vector::get_angle(float x, float y)
{
float tan = 0.0f;
float angle = 0.0f;
if (x != 0)
{
tan = y / x;
angle = atan(tan);
// this setting applies to the graphic reference system
if (x > 0 && y < 0) angle = 2 * M_PI + angle;
if (x < 0 && y > 0) angle += M_PI;
if (x < 0 && y < 0) angle += M_PI;
}
if (x == 0)
{
if (y > 0) angle = M_PI_2;
if (y < 0) angle = 3 * M_PI_2;
}
if (y == 0)
{
if (x > 0) angle = 0.0f;
if (x < 0) angle = M_PI;
}
return angle;
}
float Vector::get_angle(Vector v)
{
return get_angle(v.x, v.y);
}
void Vector::to_string()
{
cout << "x: " + std::to_string(x) + " y: " + std::to_string(y) << endl;
}
Vector operator+(const Vector &v1, const Vector &v2)
{
Vector tmp;
tmp.set(v1.x + v2.x, v1.y + v2.y);
return tmp;
}
Vector operator-(const Vector &v1, const Vector &v2)
{
return v1 + Vector(-v2.x, -v2.y);
}
Vector Vector::operator+=(const Vector &v)
{
set(x + v.x, y + v.y);
return *this;
}
Vector Vector::operator=(const Vector &v)
{
set(v.x, v.y);
return *this;
}
bool Vector::operator==(const Vector &v)
{
return
(
(x == v.x)
&&
(y == v.y)
);
}
bool Vector::operator!=(const Vector &v)
{
return !(*this == v);
}
Thanks in advance!
Just add the following two methods:
void normalize()
{
float scalar = 1.0 / this->get_abs();
this->x *= scalar;
this->y *= scalar;
}
And:
static Vector get_unit(const Vector &v)
{
float scalar = 1.0 / v.get_abs();
return Vector(v.x * scalar, v.y * scalar);
}
I am supposed to write a program which has to generate a triangle function, calculate the derivative using forward and backward divided differences and differentiate the triangle function.
So, I wrote some code and have only one problem:
include\MyClass.h|12|note: no known conversion for argument 1 from 'float (MyClass::)(int, float, float)' to 'float ()(int, float, float)'|
My code:
main.cpp
#include <iostream>
#include "MyClass.h"
using namespace std;
int main()
{
MyClass object (3,4,2,0.1);
for (float i=object.x; i<2.5; i+=0.01)
{
cout << object.Triangle(10, 3.14, i) << " ";
}
cout << "////////////////////";
for (float i=object.x; i<2.5; i+=0.01)
{
cout << object.Derivative(&object.Triangle, i, object.con) << " ";
}
}
MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
public:
MyClass();
MyClass(int k_max, float omega, float x, float con);
~MyClass();
float Triangle (int k_max, float omega, float x);
float Derivative (float (*w) (int k_max, float omega, float x), float var, float con);
float DerivativeCntr (float (*w) (int k_max, float omega, float x), float var, float con);
int k_max;
float omega, x, result, con;
};
#endif // MYCLASS_H
MyClass.cpp
#include "MyClass.h"
MyClass::MyClass() {}
MyClass::~MyClass() {}
MyClass(int K_max, float Omega, float X, float Con)
{
k_max=K_max;
omega=Omega;
x=X;
con=Con;
}
///////////////////////////////////////////////
float Triangle (int k_max, float omega, float x)
{
result=0;
for int (i=0; i<=k_max; i++)
{
result += ( 8*pow(-1, i)*(sin((2*i+1)*omega*x ) / ( pow(2*i+1, 2) * pow(M_PI, 2) )
}
return result;
}
///////////////////////////////////////////////
float Derivative (float (*w) (int k_max, float omega, float x), float var, float con)
{
float result = (w(10, 3.14, var+con) - w(10, 3.14, var))/var;
return result;
}
///////////////////////////////////////////////
float DerivativeCntr (float (*w) (int k_max, float omega, float x), float var, float con)
{
float result=(w(10, 3.14, var)-w(10, 3.14, var-con))/2*var;
return result;
}
I would really appreciate your help, thanks!
EDIT:
I've got this program working, but it's recommended to use a class and required to use a pointer to the function. That's my non object-oriented code:
https://ideone.com/mtPLAo
You have several errors of syntactical nature in your code.
In MyClass.h, change into
float Derivative (float *w, int k_max, float omega, float x, float var, float con);
float DerivativeCntr (float *w, int k_max, float omega, float x, float var, float con);
In MyClass.cpp, all member functions should be prefixed by MyClass:: and also the same for the constructor that takes arguments.
I have written three dimensional integration code which calls a gaussian quadrature routine to do the integration as shown below:
#include <iostream>
#include <cmath>
using namespace std;
float qgaus(float (*func)(float), float a, float b)
{
int j;
float xr,xm,dx,s;
static float x[]={0.0,0.1488743389,0.4333953941,
0.6794095682,0.8650633666,0.9739065285};
static float w[]={0.0,0.2955242247,0.2692667193,
0.2190863625,0.1494513491,0.0666713443};
xm = 0.5*(b+a);
xr = 0.5*(b-a);
s = 0;
for (j=1;j<=5;j++)
{
dx=xr*x[j];
s += w[j]*((*func)(xm+dx)+(*func)(xm-dx));
}
return s *= xr;
}
float func(float x,float y,float z)
{
float f = x*y*z;
return f;
}
float yy1(float x)
{
float y = x;
return y;
}
float yy2(float x)
{
float y = 2*x;
return y;
}
float z1(float x,float y)
{
float z = 5*x*y;
return z;
}
float z2(float x,float y)
{
float z = 10*x*x*y;
return z;
}
static float xsav,ysav;
static float (*nrfunc)(float,float,float);
float quad3d(float (*func)(float, float, float), float x1, float x2)
{
float qgaus(float (*func)(float), float a, float b);
float f1(float x);
nrfunc=func;
return qgaus(f1,x1,x2);
}
float f1(float x)
{
float qgaus(float (*func)(float), float a, float b);
float f2(float y);
float yy1(float),yy2(float);
xsav=x;
return qgaus(f2,yy1(x),yy2(x));
}
float f2(float y)
{
float qgaus(float (*func)(float), float a, float b);
float f3(float z);
float z1(float,float),z2(float,float);
ysav = y;
return qgaus(f3,z1(xsav,y),z2(xsav,y));
}
float f3(float z)
{
return (*nrfunc)(xsav,ysav,z);
}
int main ()
{
float R;
R = quad3d(func, 0, 1);
cout << R << endl;
}
This code works perfectly for any three dimensional function I have tested it with. I have attempted to modify it to compute a four dimensional function by replacing the 3d routine with a 4d one:
static float wsav,xsav,ysav;
static float (*nrfunc)(float,float,float,float);
float quad4d(float (*func)(float, float, float, float), float w1, float w2)
{
float qtrap(float (*func)(float), float a, float b);
float f1(float w);
nrfunc=func;
return qtrap(f1,w1,w2);
}
float f1(float w)
{
float qtrap(float (*func)(float), float a, float b);
float f2(float x);
float x1(float),x2(float);
wsav = w;
return qtrap(f2,x1(w),x2(w));
}
float f2(float x)
{
float qtrap(float (*func)(float), float a, float b);
float f3(float y);
float yy1(float,float),yy2(float,float);
xsav = x;
return qtrap(f2,yy1(wsav,x),yy2(wsav,x));
}
float f3(float y)
{
float qtrap(float (*func)(float), float a, float b);
float f4(float z);
float z1(float,float,float),z2(float,float,float);
ysav = y;
return qtrap(f3,z1(wsav,xsav,y),z2(wsav,xsav,y));
}
float f4(float z)
{
float t = (*nrfunc)(wsav,xsav,ysav,z);
return t;
}
This code compiles correctly, but will output "Segmentation fault: 11" when I run it. From what I understand, this implies that there is either some sort of problem with the arrays or a memory allocation error, but neither seem to make sense since there was no problem with the 3d case. Any help with this would be greatly appreciated.
Ok, so I'd like to input a one-letter character and three numbers into a structure using scanf, and I want to print all four of them by using a function that prints it. But everytime i run it i get errors saying that i can't run it, or sometimes it prints everything right except the character part, where it would just go as blank.. what could be possibly wrong with this??
#include <stdio.h>
struct Score
{
char a;
float x, y, z;
};
void main(void)
{
void avg(char *a, float x, float y, float z);
char a1 = 'b';
float x1 = 0, y1 = 0, z1 = 0;
printf("enter an alphaber\n");
fflush(stdin);
scanf_s("%c", &a1);
printf("enter three numbers (ex:1,2,3)\n");
fflush(stdin);
scanf_s("%f,%f,%f", &x1, &y1, &z1);
struct Score s1 = { a1, x1, y1, z1 };
avg(s1.a, s1.x, s1.y, s1.z);
}
void avg(char *a, float x, float y, float z)
{
printf("%c (%f,%f,%f) \n", a, x, y, z);
}
The signature of avg() is wrong. The first argument should be not char* but char.
Because I hate MSVC-specific code, your code should be like this.
Note that you should check whether readings are successful.
#include <stdio.h>
struct Score
{
char a;
float x, y, z;
};
int main(void)
{
/* declareing function inside function is unusual, but not bad */
void avg(char a, float x, float y, float z);
char a1 = 'b';
float x1 = 0, y1 = 0, z1 = 0;
printf("enter an alphaber\n");
if (scanf("%c", &a1) != 1) {
puts("read error");
return 1;
}
printf("enter three numbers (ex:1,2,3)\n");
if (scanf("%f,%f,%f", &x1, &y1, &z1) != 3) {
puts("read error");
return 1;
}
struct Score s1 = { a1, x1, y1, z1 };
avg(s1.a, s1.x, s1.y, s1.z);
}
void avg(char a, float x, float y, float z)
{
printf("%c (%f,%f,%f) \n", a, x, y, z);
}