I have written a code that performs numerical integrations—one using the Gauss method and the other using the trapezoidal method. For the Gauss method, I have five separate text files containing the weight-points (i.e., the zeros of the Laguerre polynomials) for different orders. These are necessary for the integration.
The struct defines my integrands, which depend on the temperature i and the chemical potential j. x is my integration variable and k the cases to calculate the integrands. Additionally, the function includes the necessary implementations for both the trapezoidal and Gauss integration methods.
In the main function, I use a loop to perform the integration for different temperatures and chemical potentials. The loop also contains expressions required for the calculations.
Can someone tell me why my program is taking so long to run, which operation is the slowest, and how I can efficiently improve it?
So far, I have optimized the program by introducing structs. However, it still takes a while to compute values.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// Constants
const double y = 2.0;
const double v = 1.0;
const double m = 938;
const double vorfac = 2.0 * M_PI * M_PI ;
// Gauss-Laguerre
const int n = 32; // Order of Gauss-Laguerre
double a = 0.0; // Power of x, must be specified for each case in the function
typedef struct
{
double E , f_plus, f_minus, f_S_plus, f_S_minus ;
} FuncBaseresult;
FuncBaseresult FuncBase(double x, double T, double mu)
{
FuncBaseresult res;
res.E = (sqrt(x*x + m*m ));
double exp_E_T = exp(res.E/ T);
double exp_mu_T = exp(mu / T);
res.f_minus = 1.0 / (exp_E_T / exp_mu_T + v);
res.f_plus = 1.0 / (exp_E_T * exp_mu_T + v);
res.f_S_minus = - (mu - res.E) * exp( res.E / T + mu / T) * 1.0/T * 1.0/T * 1.0/(pow((v * exp(mu/T) + exp(res.E/T)) , 2));
res.f_S_plus = (mu + res.E) * exp( res.E / T + mu / T) * 1.0/T * 1.0/T * 1.0/(pow(( exp( res.E / T + mu / T) + v ) , 2));
return res;
}
double Function(int k, double x, double T, double mu) // Integrand
{
FuncBaseresult base = FuncBase(x, T, mu);
if (k == 0)
{
a = 2.0;
return y/(vorfac) * x*x * (base.E-m) * (base.f_minus + base.f_plus); // Energy density
}
if (k == 1)
{
a = 4.0;
return y /(vorfac) * 1.0 / 3.0 * x*x*x*x * 1.0/base.E * (base.f_minus + base.f_plus); // Pressure
}
if (k == 2)
{
a = 4;
return y /(vorfac) * 1.0 / 3.0 * x*x*x*x * 1.0/base.E * (base.f_S_minus + base.f_S_plus);
}
if (k == 3)
{
a = 2;
return y / (vorfac) * x*x * ( base.f_minus + base.f_plus); // Particle density
}
return 0;
}
double x_roots[32]; // Global speichern
void getroots() {
char filename[10];
sprintf(filename, "a=%d.txt", (int)a);
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Error opening file!\n");
exit(1);
}
for (int i = 0; i < 32; i++) {
fscanf(file, "%lf", &x_roots[i]);
}
fclose(file);
}
double fac(int n)
{
double res = 1;
for (int i = 1; i <= n; i++)
{
res *= i;
}
return res;
}
double laguerre(int n, double a, double x) {
if (n == 0) return 1.0;
if (n == 1) return 1.0 + a - x;
double L0 = 1.0;
double L1 = 1.0 + a - x;
double L2 = 0.0;
for (int i = 2; i <= n; i++) {
L2 = ((2 * i - 1 + a - x) * L1 - (i - 1 + a) * L0) / i;
L0 = L1;
L1 = L2;
}
return L1;
}
double Gauss(int k, double *x, double T, double mu)
{
double fac_n = fac(n);
double fac_a = fac(a);
double fac_na = fac(n+a);
double res;
res = 0;
res *= Function(k, 0, T, mu);
getroots(x);
for (int i = 0; i < 32; i++)
{
double lag_val = laguerre(n + 1, a , x[i]); // EINMAL berechnen
res += Function(k, x[i], T, mu) * exp(x[i]) * x[i] * fac_na /
(fac_n * (n + 1) * (n + 1) * pow(lag_val, 2.0) * pow(x[i], a));
}
return res;
}
// Trapezoidal method
const double e = 1e-5; // Precision until stopping, method stops when new terms contribute less than this value
double d = 1e-3; // Interval size
double trapez(int k, double T, double mu)
{
double res = 0;
for (int i = 1; ;i++)
{
double f_val = Function(k, i * d, T, mu);
if(fabs(f_val) <= e *res) break;
res += d * f_val;
}
return res;
}
int main()
{
FILE *file1 = fopen("test.txt", "w");
if (file1 == NULL)
{
printf("Error opening the file!\n");
exit(1);
}
double x[32];
double temp0, temp1, temp2, temp3 ;
double Euler;
// j is mu and i is T
for (double j = 1; j < 50000; j*=30) //mu
{
fprintf(file1, "%e ", j/m); // Start line with mu
for (double i = 20; i <= 2000; i += 20) // Temperature
{
if (i == 20 || i == 1000 || i == 1500 )
{
if (j/i > 1e-5)
{
temp0 = trapez(0, i, j);
temp1 = trapez(1, i, j);
}
else
{
temp0 = Gauss(0, x, i, j);
temp1 = Gauss(1, x, i, j);
}
double k_f = sqrt(j*j - m*m); // j is mu
double P_0;
double e_0;
if (j < m)
{
P_0 = 0;
e_0 = 0;
}
else
{
P_0 = y/(24.0*M_PI*M_PI) * (j * k_f * (k_f *k_f - 3.0/2.0 * m*m) + 3.0/2.0 * pow(m ,4) * log( (k_f + j)/m ));
e_0 = y/(2.0*M_PI*M_PI) * 1.0/24.0 * (-3*asinh(k_f/m) * pow(m,4) + j * (3 * k_f * m*m + 6*pow(k_f , 3)) - 8 * pow(k_f , 3) *m );
}
if(temp0 < 1e-148 || temp1 < 1e-148 )
{
temp0 = 8.170380e-170;
temp1 = 1.630096e-169 ;
}
double gamma2 = ((temp1 - P_0)/(temp0 - e_0 )) + 1 ;
fprintf(file1, " T/m = %e gamma2 = %e ||",i/m , gamma2);
}
}
fprintf(file1, "\n");
}
fclose(file1);
}
a=0.txt
0.04448936583326701388
0.23452610951961938568
0.57688462930187434097
1.07244875381808424386
1.72240877643981793454
2.52833670644600161381
3.49221327314977170175
4.61645676498042956126
5.90395853784575752599
7.35812653405240890692
8.98294165535760669172
10.78301623367992156943
12.76371176580493127517
14.93115838768134118197
17.29244179823459504064
19.85579651978946458257
22.63255043922785247901
25.63028835810287731078
28.86407464765523656069
32.35453780640911247701
36.10748356744834808296
40.18143213593468487943
44.42889069562876613873
49.27734571508544547669
54.27154725396455603459
59.94403361568824095684
65.93755634763675743670
72.70366493025684917484
80.18138178742300681279
88.73656778030174052674
98.82940647607993867041
111.75140449427495070722
a=1.txt
0.11125830781785717161
0.37321887563579131397
0.78564593354865541741
1.34945557597258414262
2.06595254242072190465
2.93682515070008509639
3.96416490359780615549
5.15049471449633600173
6.49880480363346535455
8.01259753882315450824
9.69594322587912316180
11.55354602478912795505
13.59083274319271872344
15.81411321911575207366
18.23009213725826782593
20.84849310402791644492
23.67515123618571948327
26.73438742869342021891
29.99552028898686018010
33.57676206461579226925
37.34146675218031674603
41.46495585451080501116
45.88785208864274522966
50.61186477968586672205
55.84742703528508656063
61.37005353675105112643
67.57416441994908495872
74.30608614857651161856
81.87696228978541057586
90.48403294680814212825
100.64522034615339407537
113.64498858551716864440
a=2.txt
0.19694392214666700536
0.52948786605016606721
1.01026981913835722793
1.64061619167524574969
2.42200673329678828338
3.35625823788337251941
4.44557318796410427808
5.69257571438529819119
7.10035054452460823171
8.67248886206972890989
10.41314853479853397289
12.32708584885750902060
14.41998155470366604902
16.69734167676762481847
19.16999706336005004914
21.83522688699483182972
24.73213241077598212314
27.78526342547449345943
31.19219783012959368307
34.70691588805129157436
38.66256189358491468511
42.80051011906167701682
47.08750526143398928980
52.18367944128409874338
57.16929227843460381564
63.00419269308171266175
69.05512238051676376926
75.96022652445722656012
83.54518851546569635502
92.22284353379730248434
102.44781654325494457680
115.52491081961949248580
a=3.txt
0.29961872904924113925
0.70198106535399051875
1.24974569814540892310
1.94514382444181599396
2.78994869155615976553
3.78614305436027143159
4.93605294225746238368
6.24240683549429142829
7.70838397617374493365
9.33766076211349371761
11.13449041432764907711
13.10369376236954686021
15.25092379849237644862
17.58290560002000546547
20.10295780865619619249
22.84125955809728836243
25.74399385028829456701
32.24991591099860244185
36.02127473917757782829
43.96048256063561865403
48.61417396672651847211
58.78464627570348710606
64.41104405231406815346
70.68058601977669752614
77.53803838832618566812
85.21629249041217235572
93.94733619882016739666
104.23846159852307380334
117.39174740382649986259
39.76478080625362565570
53.26931493053049848641
28.98039246758906983814
a=4.txt
0.41790923492851933529
0.88953757977417469149
1.50313435358155333965
2.26227724680885167174
3.16916090796869021062
4.22598142404881293999
5.43520757619423022788
6.79968010050789395393
8.32267392651077386745
10.00795498422072071776
11.85983746177703679336
13.88318378640620309739
16.08389351549142176623
18.46814636381402863208
23.81677094107534387035
26.81166653707526492667
30.06799305570848446223
33.37113780215095459880
40.76480747240096746964
45.63178176901075744354
72.06876424060635599744
119.24607803365869074241
21.04413848219094163028
66.17739535280246343518
37.32268320943082784424
55.39666901945717114586
95.66257883144125173658
49.44734140119586385254
59.78453975634411676765
86.86244827669744950072
79.18793460362063285629
106.01725817767682258363
I have now tried to implement the suggestions and optimized my code. The code is running faster, but some integrands are being calculated incorrectly, for example when k==3. Did I make any mistakes in the implementation?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <omp.h> // OpenMP für Parallelisierung
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// Konstanten
const double y = 2.0;
const double v = 1.0;
const double m = 930;
const double vorfac = 2.0 * M_PI * M_PI;
const int n = 32; // Gauss-Laguerre Ordnung
double a = 0.0;
double x_roots[32]; // Save weights
double fac_lookup[33]; // save fac!
typedef struct {
double E, f_plus, f_minus, f_S_plus, f_S_minus;
} FuncBaseresult;
// save fac
void init_fac_table() {
fac_lookup[0] = 1.0;
for (int i = 1; i <= 32; i++) {
fac_lookup[i] = fac_lookup[i - 1] * i;
}
}
void getroots(double a_value) {
char filename[10];
sprintf(filename, "a=%d.txt", a_value);
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Error opening file: %s\n", filename);
exit(1);
}
for (int i = 0; i < 32; i++) {
fscanf(file, "%lf", &x_roots[i]);
}
fclose(file);
}
FuncBaseresult FuncBase(double x, double T, double mu) {
FuncBaseresult res;
res.E = sqrt(x*x + m*m);
double exp_E_T = exp(res.E / T);
double exp_mu_T = exp(mu / T);
double exp_sum = exp_E_T * exp_mu_T;
double exp_diff = exp_E_T / exp_mu_T;
res.f_minus = 1.0 / (exp_diff + v);
res.f_plus = 1.0 / (exp_sum + v);
double denom1 = (v * exp_mu_T + exp_E_T);
double denom2 = (exp_sum + v);
res.f_S_minus = - (mu - res.E) * exp(exp_E_T + exp_mu_T) * (1.0 / (T*T)) / (denom1 * denom1);
res.f_S_plus = (mu + res.E) * exp(exp_E_T + exp_mu_T) * (1.0 / (T*T)) / (denom2 * denom2);
return res;
}
double Function(int k, double x, double T, double mu) {
FuncBaseresult base = FuncBase(x, T, mu);
if (k == 0) {
a = 2.0;
return y / vorfac * x*x * (base.E - m) * (base.f_minus + base.f_plus);
}
if (k == 1) {
a = 4.0;
return y / (vorfac * 3.0) * x*x*x*x / base.E * (base.f_minus + base.f_plus);
}
if (k == 2) {
a = 4.0;
return y / (vorfac * 3.0) * x*x*x*x / base.E * (base.f_S_minus + base.f_S_plus);
}
if (k == 3) {
a = 2.0;
return y / vorfac * x*x * (base.f_minus + base.f_plus);
}
}
// Laguerre-recursive
double laguerre(int n, double a, double x) {
double L0 = 1.0, L1 = 1.0 + a - x, L2;
for (int i = 2; i <= n; i++) {
L2 = ((2 * i - 1 + a - x) * L1 - (i - 1 + a) * L0) / i;
L0 = L1;
L1 = L2;
}
return L1;
}
// Gauss-Quad
double Gauss(int k, double T, double mu) {
double fac_n = fac_lookup[n];
double fac_a = fac_lookup[(int)a];
double fac_na = fac_lookup[n + (int)a];
double res = 0;
for (int i = 0; i < 32; i++) {
double lag_val = laguerre(n + 1, a, x_roots[i]);
res += Function(k, x_roots[i], T, mu) * exp(x_roots[i]) * x_roots[i] * fac_na /
(fac_n * (n + 1) * (n + 1) * pow(lag_val, 2.0) * pow(x_roots[i], a));
}
return res;
}
// Trapez
const double e = 1e-5;
double d = 1e-3;
double trapez(int k, double T, double mu) {
double res = 0, prev_res = 0;
double h = d;
for (int i = 1; ; i++) {
double f_val = Function(k, i * h, T, mu);
res += h * f_val;
if (fabs(res - prev_res) < e * res) break;
prev_res = res;
h *= 0.9;
}
return res;
}
int main() {
FILE *file1 = fopen("test.txt", "w");
if (!file1) {
printf("Error opening the file!\n");
return 1;
}
init_fac_table();
getroots(0);
double temp0;
double temp1;
#pragma omp parallel for schedule(dynamic) // Parallelisierung
for (double j = 1; j < 1e6; j *= 10) { // mu
fprintf(file1, "%e ", j ); // Start line with mu
for (double i = 20; i <= 2000; i += 20) { // Temperature
if (i == 20 || i == 400 || i == 1000 || i == 2000){
double k_f = sqrt(j * j - m * m);
double P_0 = (j >= m) ? y / (24.0 * M_PI * M_PI) * (j * k_f * (k_f * k_f - 3.0 / 2.0 * m * m) + 3.0 / 2.0 * pow(m, 4) * log((k_f + j) / m)) : 0 ;
double e_0 = (j>=m) ? y / (2.0 * M_PI * M_PI) * 1.0 / 24.0 * (-3 * asinh(k_f / m) * pow(m, 4) + j * (3 * k_f * m * m + 6 * pow(k_f, 3)) - 8 * pow(k_f, 3) * m) : 0 ;
double P_norm = 2 * (7.0 / 4.0 * M_PI * M_PI / 90 * pow(i, 4) + 1.0 / 12.0 * pow(j * i, 2) + 1.0 / 24.0 * 1 / pow(M_PI, 2) * pow(j, 4)); //Faktor 2 am Anfang, wegen Normierung von Teilchen-Antiteilchen
double S_norm = 2*(7.0 * M_PI * M_PI / 90 * pow(i, 3) + 1.0 / 6.0 * pow(j, 2) * i);
double n_norm;
if (j == 0)
{
n_norm = 2.0;
}
else
{
n_norm = 2*(1.0 / 6.0 * j * pow(i, 2) + 1.0 / 6.0 * 1 / (pow(M_PI, 2))*pow(j, 3));
}
double temp0 = (j / i > 1e-5) ? trapez(0, i, j) : Gauss(0, i, j);
double temp1 = (j / i > 1e-5) ? trapez(1, i, j) : Gauss(1, i, j);
double temp3 = (j / i > 1e-5) ? trapez(3, i, j) : Gauss(3, i, j);
temp3=temp3/n_norm;
double gamma2 = (temp1 - P_0) / (temp0 - e_0) + 1;
fprintf(file1, " n = %e ||", temp3);
}
}
fprintf(file1, "\n");
}
fclose(file1);
return 0;
}
```
getrootsreads thea*.txtfiles intox_roots, which is never referenced. It is as good as not read them at all. 2 I tried to run your code, and found thattrapeznever reachesbreak. Back to the drawing board I guess. VTC. \$\endgroup\$