xref: /petsc/src/sys/classes/random/tutorials/ex2.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 static char help[] = "Tests PetscRandom functions.\n\n";
2 
3 #include <petscsys.h>
4 
5 #define PETSC_MAXBSIZE     40
6 #define DATAFILENAME "ex2_stock.txt"
7 
8 struct himaInfoTag {
9   PetscInt    n;
10   PetscReal   r;
11   PetscReal   dt;
12   PetscInt    totalNumSim;
13   PetscReal   *St0;
14   PetscReal   *vol;
15 };
16 typedef struct himaInfoTag himaInfo;
17 
18 PetscErrorCode readData(MPI_Comm,himaInfo *);
19 PetscReal mcVal(PetscReal, PetscReal, PetscReal, PetscReal, PetscReal);
20 void exchangeVal(PetscReal*, PetscReal*);
21 PetscReal basketPayoff(PetscReal[], PetscReal[], PetscInt, PetscReal,PetscReal, PetscReal[]);
22 PetscErrorCode stdNormalArray(PetscReal*, PetscInt,PetscRandom);
23 PetscInt divWork(PetscMPIInt, PetscInt, PetscMPIInt);
24 
25 /*
26    Contributed by Xiaoyan Zeng <zengxia@iit.edu> and Liu, Kwong Ip" <kiliu@math.hkbu.edu.hk>
27 
28    Example of usage:
29      mpiexec -n 4 ./ex2 -num_of_stocks 30 -interest_rate 0.4 -time_interval 0.01 -num_of_simulations 10000
30 */
31 
32 int main(int argc, char *argv[])
33 {
34   PetscReal      r,dt;
35   PetscInt       n;
36   unsigned long  i,myNumSim,totalNumSim,numdim;
37   PetscReal      *vol, *St0, x, totalx;
38   PetscMPIInt    size,rank;
39   PetscReal      *eps;
40   himaInfo       hinfo;
41   PetscRandom    ran;
42   PetscErrorCode ierr;
43 
44   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
45   ierr = PetscRandomCreate(PETSC_COMM_WORLD,&ran);CHKERRQ(ierr);
46   ierr = PetscRandomSetFromOptions(ran);CHKERRQ(ierr);
47 
48   ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size);CHKERRMPI(ierr);
49   ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);CHKERRMPI(ierr);
50 
51   hinfo.n           = 31;
52   hinfo.r           = 0.04;
53   hinfo.dt          = 1.0/12;   /* a month as a period */
54   hinfo.totalNumSim = 1000;
55 
56   ierr = PetscOptionsGetInt(NULL,NULL,"-num_of_stocks",&(hinfo.n),NULL);CHKERRQ(ierr);
57   if (hinfo.n <1 || hinfo.n > 31) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only 31 stocks listed in stock.txt. num_of_stocks %D must between 1 and 31",hinfo.n);
58   ierr = PetscOptionsGetReal(NULL,NULL,"-interest_rate",&(hinfo.r),NULL);CHKERRQ(ierr);
59   ierr = PetscOptionsGetReal(NULL,NULL,"-time_interval",&(hinfo.dt),NULL);CHKERRQ(ierr);
60   ierr = PetscOptionsGetInt(NULL,NULL,"-num_of_simulations",&(hinfo.totalNumSim),NULL);CHKERRQ(ierr);
61 
62   n           = hinfo.n;
63   r           = hinfo.r;
64   dt          = hinfo.dt;
65   totalNumSim = hinfo.totalNumSim;
66   ierr        = PetscMalloc1(2*n+1,&hinfo.vol);CHKERRQ(ierr);
67   vol         = hinfo.vol;
68   St0         = hinfo.St0 = hinfo.vol + n;
69   ierr        = readData(PETSC_COMM_WORLD,&hinfo);CHKERRQ(ierr);
70 
71   numdim = n*(n+1)/2;
72   if (numdim%2 == 1) numdim++;
73   ierr = PetscMalloc1(numdim,&eps);CHKERRQ(ierr);
74 
75   myNumSim = divWork(rank,totalNumSim,size);
76 
77   x = 0;
78   for (i=0; i<myNumSim; i++) {
79     ierr = stdNormalArray(eps,numdim,ran);CHKERRQ(ierr);
80     x += basketPayoff(vol,St0,n,r,dt,eps);
81   }
82 
83   ierr = MPI_Reduce(&x, &totalx, 1, MPIU_REAL, MPIU_SUM,0,PETSC_COMM_WORLD);CHKERRMPI(ierr);
84   /* payoff = exp(-r*dt*n)*(totalx/totalNumSim);
85   ierr = PetscPrintf(PETSC_COMM_WORLD,"Option price = $%.3f using %ds of %s computation with %d %s for %d stocks, %d trading period per year, %.2f%% interest rate\n",
86    payoff,(int)(stop - start),"parallel",size,"processors",n,(int)(1/dt),r);CHKERRQ(ierr); */
87 
88   ierr = PetscFree(vol);CHKERRQ(ierr);
89   ierr = PetscFree(eps);CHKERRQ(ierr);
90   ierr = PetscRandomDestroy(&ran);CHKERRQ(ierr);
91   ierr = PetscFinalize();
92   return ierr;
93 }
94 
95 PetscErrorCode stdNormalArray(PetscReal *eps, PetscInt numdim, PetscRandom ran)
96 {
97   PetscInt       i;
98   PetscScalar    u1,u2;
99   PetscReal      t;
100   PetscErrorCode ierr;
101 
102   PetscFunctionBegin;
103   for (i=0; i<numdim; i+=2) {
104     ierr = PetscRandomGetValue(ran,&u1);CHKERRQ(ierr);
105     ierr = PetscRandomGetValue(ran,&u2);CHKERRQ(ierr);
106 
107     t        = PetscSqrtReal(-2*PetscLogReal(PetscRealPart(u1)));
108     eps[i]   = t * PetscCosReal(2*PETSC_PI*PetscRealPart(u2));
109     eps[i+1] = t * PetscSinReal(2*PETSC_PI*PetscRealPart(u2));
110   }
111   PetscFunctionReturn(0);
112 }
113 
114 PetscReal basketPayoff(PetscReal vol[], PetscReal St0[], PetscInt n, PetscReal r,PetscReal dt, PetscReal eps[])
115 {
116   PetscReal Stk[PETSC_MAXBSIZE], temp;
117   PetscReal payoff;
118   PetscInt  maxk,i,j;
119   PetscInt  pointcount=0;
120 
121   for (i=0;i<n;i++) Stk[i] = St0[i];
122 
123   for (i=0;i<n;i++) {
124     maxk = 0;
125     for (j=0;j<(n-i);j++) {
126       Stk[j] = mcVal(Stk[j],r,vol[j],dt,eps[pointcount++]);
127       if ((Stk[j]/St0[j]) > (Stk[maxk]/St0[maxk])) maxk = j;
128     }
129     exchangeVal(Stk+j-1,Stk+maxk);
130     exchangeVal(St0+j-1,St0+maxk);
131     exchangeVal(vol+j-1,vol+maxk);
132   }
133 
134   payoff = 0;
135   for (i=0; i<n; i++) {
136     temp = (Stk[i]/St0[i]) - 1;
137     if (temp > 0) payoff += temp;
138   }
139   return payoff;
140 }
141 
142 PetscErrorCode readData(MPI_Comm comm,himaInfo *hinfo)
143 {
144   PetscInt       i;
145   FILE           *fd;
146   char           temp[50];
147   PetscErrorCode ierr;
148   PetscMPIInt    rank;
149   PetscReal      *v = hinfo->vol, *t = hinfo->St0;
150   PetscInt       num=hinfo->n;
151 
152   PetscFunctionBeginUser;
153   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
154   if (!rank) {
155     ierr = PetscFOpen(PETSC_COMM_SELF,DATAFILENAME,"r",&fd);CHKERRQ(ierr);
156     for (i=0;i<num;i++) {
157       double vv,tt;
158       if (fscanf(fd,"%s%lf%lf",temp,&vv,&tt) != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Badly formatted input file\n");
159       v[i] = vv;
160       t[i] = tt;
161     }
162     fclose(fd);
163   }
164   ierr = MPI_Bcast(v,2*num,MPIU_REAL,0,PETSC_COMM_WORLD);CHKERRMPI(ierr);
165   /* ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] vol %g, ... %g; St0 %g, ... %g\n",rank,hinfo->vol[0],hinfo->vol[num-1],hinfo->St0 [0],hinfo->St0[num-1]); */
166   PetscFunctionReturn(0);
167 }
168 
169 void exchangeVal(PetscReal *a, PetscReal *b)
170 {
171   PetscReal t;
172 
173   t  = *a;
174   *a = *b;
175   *b = t;
176 }
177 
178 PetscReal mcVal(PetscReal St, PetscReal r, PetscReal vol, PetscReal dt, PetscReal eps)
179 {
180   return (St * PetscExpReal((r-0.5*vol*vol)*dt + vol*PetscSqrtReal(dt)*eps));
181 }
182 
183 PetscInt divWork(PetscMPIInt id, PetscInt num, PetscMPIInt size)
184 {
185   PetscInt numit;
186 
187   numit = (PetscInt)(((PetscReal)num)/size);
188   numit++;
189   return numit;
190 }
191 
192 /*TEST
193 
194    build:
195       requires: !comple
196       output_file: output/ex1_1.out
197 
198    test:
199       nsize: 2
200       output_file: output/ex1_1.out
201       localrunfiles: ex2_stock.txt
202 
203 TEST*/
204