Problem z zastąpieniem części kodu poprzez funkcje

0

Witam,
Mam problem z zastąpieniem części kodu funkcją i wszystko by było dobrze gdyby nie to że jak już zastąpiłem to co trzeba to pliku źródłowego nie mogę skompilować i nie rozumiem komunikatu dla jakiego nie może mi poprawnie się kompilować (komunikat z DEV c++ "void value not ignored as it ought to be" ).

Kod programu:

 #include <stdio.h>
 #include <math.h>
 #include <gsl/gsl_sf_coupling.h>
 #include "numerical.h"


//To są wyliczone kolejne silnie wykorzystywane w programie
 const double ff [20]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,
                       479001600,6227020800,87178291200,1307674368000,20922789888000,
                       355687428096000,6402373705728000,121645100408832000};


 void gausslaguerre (double xx [],double ww [],int n,double a) {
   int i,its,j;
   double ai,p1,p2,p3,pp,z,z1;
   for (i=1;i<=n;i++) {
     if (i==1)
       z=(1+a)*(3+0.92*a)/(1+2.4*n+1.8*a);
     else if (i==2)
       z+=(15+6.25*a)/(1+0.9*a+2.5*n);
     else {
       ai=i-2;
       z+=((1+2.55*ai)/(1.9*ai)+1.26*ai*a/(1+3.5*ai))*(z-xx [i-3])/(1+0.3*a); }
     for (its=1;its<10;its++) {
       p1=1;
       p2=0;
       for (j=1;j<=n;j++) {
         p3=p2;
         p2=p1;
         p1=((2*j-1+a-z)*p2-(j-1+a)*p3)/j; }
       pp=(n*p1-(n+a)*p2)/z;
       z1=z;
       z=z1-p1/pp;
       if (fabs (z-z1)<=3e-14)
         break; }
     if (its>10)
       printf ("too many iterations in gausslaguerre\n");
     xx [i-1]=z;
     ww [i-1]=-exp (lgamma (a+n)-lgamma (n))/(pp*n*p2); }}


// ta funkcja liczy wielomiany lagerra występujące w części zależnej od L we wzorze wielomiany te oznaczane są literą "L" z indeksami
 double laguerre (int n,double a,double x) {
   int i;
   double l0,l1,l;
   l0=1;
   l1=1+a-x;
   if (n==0)
     return l0;
   else if (n==1)
     return l1;
   for (i=1;i<n;i++) {
     l=((2*i+a+1-x)*l1-(i+a)*l0)/(i+1);
     l0=l1;
     l1=l; }
   return l; }

static double sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))

// ta funkcja jest używane przez funkcje tqli
 double pythag (double a,double b) {
   double absa,absb;
   absa=fabs (a);
   absb=fabs (b);
   if (absa>absb)
     return absa*sqrt(1.0+SQR(absb/absa));
   else
     return (absb==0 ? 0 : absb*sqrt(1.0+SQR(absa/absb))); }

// Ta funkcja liczy poprawki do wartości własnych liczonych zgodnie ze wzorami w załączonym niżej pliku
//Funkcja ta służy do diagonalizacji macierzy trój diagonalnej
 void tqli (double dd [],double ee [],int n) {
   int m,l,iter,i,k;
   double s,r,p,g,f,d,c,b;
   for (i=1;i<n;i++)
     ee [i-1]=ee [i];
   ee [n-1]=0.0;
   for (l=0;l<n;l++) {
     iter=0;
     do {
       for (m=l;m<n-1;m++) {
         d=fabs (dd [m])+fabs (dd [m+1]);
         if ((double) (fabs (ee [m])+d)==d)
           break; }
       if (m!=l) {
         if (iter++==30)
           printf ("Too many iterations in tqli\n");
         g=(dd [l+1]-dd [l])/(2*ee [l]);
         r=pythag (g,1.0);
         g=dd [m]-dd [l]+ee [l]/(g+SIGN (r,g));
         s=c=1;
         p=0;
         for (i=m-1;i>=l;i--) {
           f=s*ee [i];
           b=c*ee [i];
           ee [i+1]=(r=pythag (f,g));
           if (r==0) {
             dd [i+1]-=p;
             ee [m]=0;
             break; }
           s=f/r;
           c=g/r;
           g=dd [i+1]-p;
           r=(dd [i]-g)*s+2*c*b;
           dd [i+1]=g+(p=s*r);
           g=c*r-b; }
         if (r==0 && i>=l)
           continue;
         dd [l]-=p;
         ee [l]=g;
         ee [m]=0; }}
     while (m!=l); }}
     
 void Clepsh (double l1, double l2, double l3, double m1, double m2, double m3) {
      pow(-1, l1-l2+m3) * sqrt(l3+1) * gsl_sf_coupling_3j (2*l1,2*l3,2*l2,2*m1,-2*m3,2*m2);
      }
     

// Program liczy poprawki do energii własnych dla efektu starka

 int main () {
   int n,l,m,i;
   double xx [10],ww [10],ll [10];
   for (n=1;n<=10;n++) {
     gausslaguerre (xx,ww,n,3);

     for (l=0;l<n-1;l++) {

       ll [l+1]=0;
       for (i=0;i<n;i++)
         ll [l+1]+=ww [i]*laguerre (n-l-1,2*l+1,xx [i])*laguerre (n-l-2,2*l+3,xx [i])*pow (xx [i],2*l+1);
//fragment z gsl_sf_coupling_3j chce zastąpić funkcją Clepsh
//Tu jest liczona część zależna tylko od L
       ll [l+1]*=sqrt ((2*l+1)*(2*l+3))*sqrt ((ff [n-l-1]/ff [n+l])*(ff [n-l-2]/ff [n+l+1]))
                   *gsl_sf_coupling_3j (2*l,2*(l+1),2,0,0,0)/4; } 

     for (m=-(n-1);m<=n-1;m++) {
       for (l=abs (m);l<=n-1;l++)
         xx [l-abs (m)]=0;
       for (l=abs (m);l<n-1;l++)
//fragment z gsl_sf_coupling_3j chce zastąpić funkcją Clepsh
//Tu liczona jest część wzoru zależna od L i M
         ww [l+1-abs (m)]=(abs (m)%2 ? -1 : 1)*gsl_sf_coupling_3j (2*l,2*(l+1),2,2*m,-2*m,0)*ll [l+1];
       tqli (xx,ww,n-abs (m));
       for (i=0;i<n-abs (m);i++)
         printf ("%5.1lf ",xx [i]);
       printf ("\n"); }
     printf ("\n"); }
   return 0; }

Prosił bym o pomoc to dla mnie bardzo ważne, a aż tak biegły w C/C++ nie jestem.

W zaznaczonych miejscach ja zrobiłem coś takiego by użyć funkcji Clepsh zamiast gsl_sf_coupling_3j:
w pierwszym miejscu

ll [l+1]*=sqrt(2*l+1)*sqrt((ff [n-l-1]/ff [n+l])*(ff [n-l-2]/ff [n+l+1]))*Clepsh(l,1,l+1,0,0,0)/(4*pow(-1, 2*l-2)); }

w drugim miejscu

ww [l+1-abs (m)]=(abs (m)%2 ? -1 : 1)*Clepsh(l,1,l+1,m,0,m)/(pow(-1, l-(l+1)+m) * sqrt(l+2))*ll [l+1];

Tak jak Koziołek napisał uzupełniłem kod kilkoma komentarzami i załączam wzory z jakich liczy program.

<url> http://img142.imageshack.us/img142/4831/screensw5.png </url> // uzywaj tagów cpp> /cpp> [mf]
0

Ty chyba startujesz w konkursie na najbardziej nieczytelny program.

0

Nie wiem czemu tak sądzisz, moim zdaniem main jest tak przejrzysty jak to możliwe, a void'y powstawiałem ponieważ z make'm w DEV'ie są problemy, a jego używam do edycji i kompilowania programów.

0

Chyba przejrzystego programu nie widziales...

Podaj komunikat bledu, bo to, ze Ty go nie rozumiesz, nie znaczy, ze ktos inny bedzie mial z nim problem.

0

Program jest czytelny tylko, że trzeba mieć jeszcze wzór z którego się korzysta (fizyka kwantowa).

Kundek dopisz jakiś komentarz i wrzuć wzór.

0

a mi się skompilował pod gcc 4.3, visual c++ też wyrzuca tylko błędy związane z brakiem "numerical.h", błąd wygląda jakby ktoś próbował przypisać do zmiennej wartość zwracaną przez funkcję typu void f(coś), program wypisuje:
0.0

0.0
3.0 -3.0
0.0

0.0
4.5 -4.5
9.0 0.0 -9.0
4.5 -4.5
0.0

0.0
6.0 -6.0
12.0 0.0 -12.0
18.0 6.0 -6.0 -18.0
12.0 0.0 -12.0
6.0 -6.0
0.0

0.0
7.5 -7.5
15.0 -0.0 -15.0
22.5 7.5 -7.5 -22.5
30.0 15.0 -0.0 -15.0 -30.0
22.5 7.5 -7.5 -22.5
15.0 -0.0 -15.0
7.5 -7.5
0.0

0.0
9.0 -9.0
18.0 -0.0 -18.0
27.0 9.0 -9.0 -27.0
18.0 36.0 -0.0 -18.0 -36.0
27.0 45.0 9.0 -9.0 -27.0 -45.0
18.0 36.0 -0.0 -18.0 -36.0
27.0 9.0 -9.0 -27.0
18.0 -0.0 -18.0
9.0 -9.0
0.0

0.0
10.5 -10.5
21.0 -0.0 -21.0
31.5 10.5 -10.5 -31.5
21.0 42.0 0.0 -21.0 -42.0
31.5 -10.5 10.5 -31.5 -52.5 52.5
42.0 63.0 21.0 -0.0 -21.0 -42.0 -63.0
31.5 -10.5 10.5 -31.5 -52.5 52.5
21.0 42.0 0.0 -21.0 -42.0
31.5 10.5 -10.5 -31.5
21.0 -0.0 -21.0
10.5 -10.5
0.0

0.0
12.0 -12.0
24.0 -0.0 -24.0
12.0 36.0 -12.0 -36.0
24.0 0.0 48.0 -24.0 -48.0
36.0 12.0 -12.0 60.0 -36.0 -60.0
48.0 24.0 0.0 72.0 -24.0 -48.0 -72.0
60.0 36.0 84.0 12.0 -12.0 -36.0 -60.0 -84.0
48.0 24.0 0.0 72.0 -24.0 -48.0 -72.0
36.0 12.0 -12.0 60.0 -36.0 -60.0
24.0 0.0 48.0 -24.0 -48.0
12.0 36.0 -12.0 -36.0
24.0 -0.0 -24.0
12.0 -12.0
0.0

0.0
13.5 -13.5
27.0 -0.0 -27.0
13.5 40.5 -13.5 -40.5
27.0 0.0 54.0 -27.0 -54.0
40.5 13.5 -13.5 67.5 -40.5 -67.5
54.0 27.0 -0.0 81.0 -27.0 -54.0 -81.0
67.5 40.5 13.5 94.5 -13.5 -40.5 -67.5 -94.5
81.0 54.0 108.0 27.0 -0.0 -27.0 -54.0 -81.0 -108.0
67.5 40.5 13.5 94.5 -13.5 -40.5 -67.5 -94.5
54.0 27.0 -0.0 81.0 -27.0 -54.0 -81.0
40.5 13.5 -13.5 67.5 -40.5 -67.5
27.0 0.0 54.0 -27.0 -54.0
13.5 40.5 -13.5 -40.5
27.0 -0.0 -27.0
13.5 -13.5
0.0

0.0
15.0 -15.0
30.0 0.0 -30.0
15.0 45.0 -15.0 -45.0
30.0 -0.0 60.0 -30.0 -60.0
45.0 15.0 -15.0 75.0 -45.0 -75.0
60.0 30.0 -0.0 90.0 -30.0 -60.0 -90.0
45.0 75.0 15.0 -15.0 105.0 -45.0 -75.0 -105.0
60.0 90.0 30.0 0.0 120.0 -30.0 -60.0 -90.0 -120.0
75.0 105.0 45.0 135.0 15.0 -15.0 -45.0 -75.0 -105.0 -135.0
60.0 90.0 30.0 0.0 120.0 -30.0 -60.0 -90.0 -120.0
45.0 75.0 15.0 -15.0 105.0 -45.0 -75.0 -105.0
60.0 30.0 -0.0 90.0 -30.0 -60.0 -90.0
45.0 15.0 -15.0 75.0 -45.0 -75.0
30.0 -0.0 60.0 -30.0 -60.0
15.0 45.0 -15.0 -45.0
30.0 0.0 -30.0
15.0 -15.0
0.0

0

a po co jest funkcja void Clepsh(...) ? bo niczego nie zwraca i niczego nie przypisuje - nie powinna być typu double i zwracać wyrażenie, które oblicza (tzn. mieć return wyrażenie)?

0

No właśnie problem mój polega na tym że bez tej funkcji program mi się kompiluje ale muszę ta funkcja zastąpić część kodu ta z funkcją GSL-ową i ona mi się nie kompiluje

0

Co do formatowania kodu. Fakt jest sformatowany, ale metodą, którą większość ludzi po prostu nie trawi.
Mniej więcej wiem co liczysz a i tak dla mnie to są krzaki.

Dla mnie takie formatowanie jest bardziej czytelne:

#include <stdio.h>
#include <math.h>
#include <gsl/gsl_sf_coupling.h>
#include "numerical.h"

//To są wyliczone kolejne silnie wykorzystywane w programie
const double ff [20]=
    {
            1,
            1,
            2,
            6,
            24,
            120,
            720,
            5040,
            40320,
            362880,
            3628800,
            39916800,
            479001600,
            6227020800,
            87178291200,
            1307674368000,
            20922789888000,
            355687428096000,
            6402373705728000,
            121645100408832000
    };

void gausslaguerre(double xx [], double ww [], int n, double a)
    {
    int i, its, j;
    double ai, p1, p2, p3, pp, z, z1;
    for (i=1; i<=n; i++)
        {
        if (i==1)
            z=(1+a)*(3+0.92*a)/(1+2.4*n+1.8*a);
        else
            if (i==2)
                z+=(15+6.25*a)/(1+0.9*a+2.5*n);
            else
                {
                ai=i-2;
                z+=((1+2.55*ai)/(1.9*ai)+1.26*ai*a/(1+3.5*ai))*(z-xx [i-3])
                        /(1+0.3*a);
                }
        for (its=1; its<10; its++)
            {
            p1=1;
            p2=0;
            for (j=1; j<=n; j++)
                {
                p3=p2;
                p2=p1;
                p1=((2*j-1+a-z)*p2-(j-1+a)*p3)/j;
                }
            pp=(n*p1-(n+a)*p2)/z;
            z1=z;
            z=z1-p1/pp;
            if (fabs(z-z1)<=3e-14)
                break;
            }
        if (its>10)
            printf("too many iterations in gausslaguerre\n");
        xx [i-1]=z;
        ww [i-1]=-exp(lgamma(a+n)-lgamma(n))/(pp*n*p2);
        }
    }

// ta funkcja liczy wielomiany lagerra występujące w części zależnej od L we 
// wzorze wielomiany te oznaczane są literą "L" z indeksami
double laguerre(int n, double a, double x)
    {
    int i;
    double l0, l1, l;
    l0=1;
    l1=1+a-x;
    if (n==0)
        return l0;
    else
        if (n==1)
            return l1;
    for (i=1; i<n; i++)
        {
        l=((2*i+a+1-x)*l1-(i+a)*l0)/(i+1);
        l0=l1;
        l1=l;
        }
    return l;
    }

static double sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))

// ta funkcja jest używane przez funkcje tqli
double pythag(double a, double b)
    {
    double absa, absb;
    absa=fabs(a);
    absb=fabs(b);
    if (absa>absb)
        return absa*sqrt(1.0+SQR(absb/absa));
    else
        return (absb==0 ? 0 : absb*sqrt(1.0+SQR(absa/absb)));
    }

// Ta funkcja liczy poprawki do wartości własnych liczonych zgodnie ze wzorami 
// w załączonym niżej pliku
// Funkcja ta służy do diagonalizacji macierzy trój diagonalnej
void tqli(double dd [], double ee [], int n)
    {
    int m, l, iter, i, k;
    double s, r, p, g, f, d, c, b;
    for (i=1; i<n; i++)
        ee [i-1]=ee [i];
    ee [n-1]=0.0;
    for (l=0; l<n; l++)
        {
        iter=0;
        do
            {
            for (m=l; m<n-1; m++)
                {
                d=fabs(dd [m])+fabs(dd [m+1]);
                if ((double) (fabs(ee [m])+d)==d)
                    break;
                }
            if (m!=l)
                {
                if (iter++==30)
                    printf("Too many iterations in tqli\n");
                g=(dd [l+1]-dd [l])/(2*ee [l]);
                r=pythag(g, 1.0);
                g=dd [m]-dd [l]+ee [l]/(g+SIGN (r,g));
                s=c=1;
                p=0;
                for (i=m-1; i>=l; i--)
                    {
                    f=s*ee [i];
                    b=c*ee [i];
                    ee [i+1]=(r=pythag(f, g));
                    if (r==0)
                        {
                        dd [i+1]-=p;
                        ee [m]=0;
                        break;
                        }
                    s=f/r;
                    c=g/r;
                    g=dd [i+1]-p;
                    r=(dd [i]-g)*s+2*c*b;
                    dd [i+1]=g+(p=s*r);
                    g=c*r-b;
                    }
                if (r==0 && i>=l)
                    continue;
                dd [l]-=p;
                ee [l]=g;
                ee [m]=0;
                }
            }
        while (m!=l);
        }
    }

void Clepsh(double l1, double l2, double l3, double m1, double m2, double m3)
    {
    pow(-1, l1-l2+m3) * sqrt(l3+1) * gsl_sf_coupling_3j(2*l1, 2*l3, 2*l2, 2
            *m1, -2*m3, 2*m2);
    }

// Program liczy poprawki do energii własnych dla efektu starka

int main()
    {
    int n, l, m, i;
    double xx [10], ww [10], ll [10];
    for (n=1; n<=10; n++)
        {
        gausslaguerre(xx, ww, n, 3);

        for (l=0; l<n-1; l++)
            {

            ll [l+1]=0;
            for (i=0; i<n; i++)
                ll [l+1]+=ww [i]*laguerre(n-l-1, 2*l+1, xx [i])*laguerre(n-l
                        -2, 2*l+3, xx [i])*pow(xx [i], 2*l+1);
            //fragment z gsl_sf_coupling_3j chce zastąpić funkcją Clepsh
            //Tu jest liczona część zależna tylko od L
            ll [l+1]*=sqrt((2*l+1)*(2*l+3))*sqrt((ff [n-l-1]/ff [n+l])
                    *(ff [n-l-2]/ff [n+l+1])) *gsl_sf_coupling_3j(2*l, 2
                    *(l+1), 2, 0, 0, 0)/4;
            }

        for (m=-(n-1); m<=n-1; m++)
            {
            for (l=abs(m); l<=n-1; l++)
                xx [l-abs (m)]=0;
            for (l=abs(m); l<n-1; l++)
                //fragment z gsl_sf_coupling_3j chce zastąpić funkcją Clepsh
                //Tu liczona jest część wzoru zależna od L i M
                ww [l+1-abs (m)]=(abs(m)%2 ? -1 : 1)*gsl_sf_coupling_3j(2*l, 2*(l
                        +1), 2, 2*m, -2*m, 0)*ll [l+1];
            tqli(xx, ww, n-abs(m));
            for (i=0; i<n-abs(m); i++)
                printf("%5.1lf ", xx [i]);
            printf("\n");
            }
        printf("\n");
        }
    return 0;
    }

A zamiast Clepsh to raczej powinno być pewnie ClebschGordon :P (przekręciłeś nazwisko). Mało tego prototyp powinien wyglądać tak (dla mnie bardziej zrozumiały):

double ClebschGordon (int l1, int m1, int l2, int m2, int J, int M );

Argumenty są liczbami kwantowymi więc powinny być liczbami całkowitymi. Jeśli chodzi i spiny (wartości połówkowe) to argumenty powinny odpowiadać podwojonej wartości krętu/spinu, wtedy nie ma problemu z połówkami.

0

to może zastąp starą Clepsh przez :

double Clepsh(double l1, double l2, double l3, double m1, double m2, double m3)
    {
    return pow(-1, l1-l2+m3) * sqrt(l3+1) * gsl_sf_coupling_3j(2*l1, 2*l3, 2*l2, 2
            *m1, -2*m3, 2*m2);
    }

i wstaw tam gdzie miała być (?zawsze lepiej wrzucić program który nie działa to jest co poprawiać :-)). gsl_sf_coupling_3j pobiera argumenty typu int więc używanie double może być niebezpieczne (może lepiej np. 2l1+0.5 zamiast 2l1).

0

Dzięki MarekR22 błąd że funkcja nie zwracała żadnej wartości poprawiłem.
Niestety współczynniki nazywają się Clebscha- Jordana a nie Gordona, Gordona wyglądają podobnie ale to nie one, i nie mogą być int'y bo wartości tam podawane nie są całkowite (dlatego w gsl_sf_coupling_3j mnożone są razy 2).

1 użytkowników online, w tym zalogowanych: 0, gości: 1