version 1.7, 2013/03/07 03:00:43 |
version 1.13, 2015/03/24 05:59:43 |
|
|
/* |
/* |
License: LGPL |
License: LGPL |
Ref: Copied from this11/misc-2011/A1/wishart/Prog |
Ref: Copied from this11/misc-2011/A1/wishart/Prog |
$OpenXM: OpenXM/src/hgm/mh/src/rk.c,v 1.6 2013/03/01 05:26:25 takayama Exp $ |
$OpenXM: OpenXM/src/hgm/mh/src/rk.c,v 1.12 2014/03/20 09:37:16 takayama Exp $ |
*/ |
*/ |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <math.h> |
#include <math.h> |
#include <string.h> |
#include <string.h> |
#include "sfile.h" |
#include "sfile.h" |
|
#include "mh.h" |
|
|
|
#include "t-gsl_errno.h" |
|
#include "t-gsl_odeiv.h" |
extern int MH_RANK; |
extern int MH_RANK; |
extern int MH_M; |
extern int MH_M; |
|
|
Line 22 static struct SFILE *Gf =NULL; |
|
Line 25 static struct SFILE *Gf =NULL; |
|
static struct SFILE *Df =NULL; |
static struct SFILE *Df =NULL; |
int MH_P95=0; |
int MH_P95=0; |
int MH_Verbose=0; |
int MH_Verbose=0; |
|
int MH_strategy=STRATEGY_DEFAULT; /* 0: rk4, 1:a-rk4 (adaptive) */ |
|
double MH_abserr = 1e-10; |
|
double MH_relerr = MH_RELERR_DEFAULT ; |
|
/* D_i = MH_abserr + MH_relerr*|y_i| |
|
If observed error E > D*110/100, the stepsize will be decreased. |
|
cf. GSL, 26.3 Adaptive Step-size control. |
|
*/ |
|
|
|
int mh_rf_for_gsl(double t,const double y[],double f[],void *params) { |
|
mh_rf(t,(double *)y,MH_RANK,f,MH_RANK); |
|
return(GSL_SUCCESS); |
|
} |
|
|
static int mypower(int x,int n) { |
static int mypower(int x,int n) { |
int a,i; |
int a,i; |
a = 1; |
a = 1; |
Line 36 int mh_gopen_file() { |
|
Line 52 int mh_gopen_file() { |
|
Gf=NULL; |
Gf=NULL; |
Df=NULL; |
Df=NULL; |
if (MH_Verbose) { |
if (MH_Verbose) { |
fprintf(stderr,"MH_Gfname=%s\n",MH_Gfname); |
oxprintfe("MH_Gfname=%s\n",MH_Gfname); |
fprintf(stderr,"MH_Dfname=%s\n",MH_Dfname); |
oxprintfe("MH_Dfname=%s\n",MH_Dfname); |
} |
} |
if (MH_RANK != mypower(2,MH_Mg)) { |
if (MH_RANK != mypower(2,MH_Mg)) { |
fprintf(stderr,"rk.c MH_RANK=%d is not equal to 2^MH_Mg=%d. input_data_file is broken.\n",MH_RANK,mypower(2,MH_Mg)); |
oxprintfe("rk.c MH_RANK=%d is not equal to 2^MH_Mg=%d. input_data_file is broken.\n",MH_RANK,mypower(2,MH_Mg)); |
mh_usage(); |
mh_usage(); |
mh_exit(-1); |
mh_exit(-1); |
} |
} |
Line 54 int mh_gopen_file() { |
|
Line 70 int mh_gopen_file() { |
|
} |
} |
Df = mh_fopen(MH_Dfname,"w",MH_byFile); |
Df = mh_fopen(MH_Dfname,"w",MH_byFile); |
if (Df == NULL) { |
if (Df == NULL) { |
fprintf(stderr,"Error to open the file %s\n",MH_Dfname); |
oxprintfe("Error to open the file %s\n",MH_Dfname); |
return(-1); |
return(-1); |
} |
} |
} |
} |
if (MH_Gfname != NULL) { |
if (MH_Gfname != NULL) { |
Gf = mh_fopen(MH_Gfname,"w",MH_byFile); |
Gf = mh_fopen(MH_Gfname,"w",MH_byFile); |
if (Gf == NULL) { |
if (Gf == NULL) { |
fprintf(stderr,"Error to open the file %s\n",MH_Gfname); |
oxprintfe("Error to open the file %s\n",MH_Gfname); |
return(-1); |
return(-1); |
} |
} |
}else return(1); |
}else return(1); |
Line 140 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
Line 156 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
h = MH_Hg; |
h = MH_Hg; |
for (i = 0; i < MH_RANK; i++) |
for (i = 0; i < MH_RANK; i++) |
y[i] = y0[i]; |
y[i] = y0[i]; |
|
if (MH_strategy == 0) { |
for (x = x0; (h>0?(x<xn):(x>xn)); x += h) { |
for (x = x0; (h>0?(x<xn):(x>xn)); x += h) { |
if (Df) show_v(x,y, MH_RANK); |
if (Df) show_v(x,y, MH_RANK); |
if (Gf) { |
if (Gf) { |
Line 149 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
Line 166 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
/* Output 95% point */ |
/* Output 95% point */ |
if (MH_P95) { |
if (MH_P95) { |
if ((MH_P95==1) && (y[0] >= 0.95)) { |
if ((MH_P95==1) && (y[0] >= 0.95)) { |
printf("x=%le, y[0]=%lf\n",x,y[0]); |
oxprintf("x=%le, y[0]=%lf\n",x,y[0]); |
MH_P95=2; |
MH_P95=2; |
}else if ((MH_P95==2) && (y[0] >=0.9500000001)) { |
}else if ((MH_P95==2) && (y[0] >=0.9500000001)) { |
printf("x=%le, y[0]=%lf\n",x,y[0]); |
oxprintf("x=%le, y[0]=%lf\n",x,y[0]); |
MH_P95=0; |
MH_P95=0; |
} |
} |
} |
} |
Line 181 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
Line 198 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
for (i = 0; i < MH_RANK; i++) |
for (i = 0; i < MH_RANK; i++) |
y[i] = y[i] + 1.0/6.0 * k1[i] + 1.0/3.0 * k2[i] + 1.0/3.0 * k3[i] + 1.0/6.0 * k4[i]; |
y[i] = y[i] + 1.0/6.0 * k1[i] + 1.0/3.0 * k2[i] + 1.0/3.0 * k3[i] + 1.0/6.0 * k4[i]; |
} |
} |
if (MH_Verbose) printf("x=%lf, y[0]=%lg\n",x,y[0]); |
}else |
|
{ |
|
extern int MH_Dp; |
|
double dh; |
|
double mh_dp_orig; |
|
double x1; |
|
const gsl_odeiv_step_type *T = gsl_odeiv_step_rkf45; |
|
gsl_odeiv_step *s = gsl_odeiv_step_alloc(T, MH_RANK); |
|
gsl_odeiv_control *c = gsl_odeiv_control_y_new(MH_abserr, MH_relerr); |
|
/* We should use the relative error. |
|
hgm.cwishart(m=5,n=20,beta=c(1,2,3,4,5),x=20,x0=2,approxdeg=20); |
|
0.977 |
|
hgm.cwishart(m=8,n=20,beta=c(1,2,3,4,5,5.6,5.7,5.8),x=30,x0=1,approxdeg=20); |
|
0.962 (non-gsl) or 0.969 (gsl, abs error 0.0, relative error 1e-10), |
|
NaN abs=0, rel=1e-5 or abs=1e-18, rel=1e-6 |
|
./mh causes NaN when rel error is 1e-10 on old 32bit machines. |
|
*/ |
|
gsl_odeiv_evolve *e = gsl_odeiv_evolve_alloc(MH_RANK); |
|
gsl_odeiv_system sys = {mh_rf_for_gsl, NULL, 0, NULL}; |
|
sys.dimension = MH_RANK; |
|
/* oxprintf("MH_RANK=%d\n",MH_RANK); */ |
|
if (x0 >= xn) {oxprintfe("Error: x0 < x must hold.\n"); mh_exit(-30);} |
|
x = x0; |
|
if (MH_Dp > 0) dh = MH_Dp*h; else dh=xn-x0; |
|
mh_dp_orig = MH_Dp; MH_Dp=1; |
|
while (x < xn) { |
|
if (Df) show_v(x,y, MH_RANK); |
|
if (Gf) { |
|
sprintf(swork,"%lf %le\n",x,y[0]); |
|
mh_fputs(swork,Gf); |
|
} |
|
/* Output 95% point */ |
|
if (MH_P95) { |
|
if ((MH_P95==1) && (y[0] >= 0.95)) { |
|
oxprintf("x=%le, y[0]=%lf\n",x,y[0]); |
|
MH_P95=2; |
|
}else if ((MH_P95==2) && (y[0] >=0.9500000001)) { |
|
oxprintf("x=%le, y[0]=%lf\n",x,y[0]); |
|
MH_P95=0; |
|
} |
|
} |
|
x1 = x+dh; |
|
while ((x < x1) && (x < xn)) { |
|
int status = gsl_odeiv_evolve_apply(e, c, s, &sys, &x, x1, &h, y); |
|
if (status != GSL_SUCCESS) { |
|
oxprintfe("gsl_odeiv_evolve_apply failed.\n"); |
|
break; |
|
} |
|
} |
|
} |
|
gsl_odeiv_evolve_free(e); |
|
gsl_odeiv_control_free(c); |
|
gsl_odeiv_step_free(s); |
|
MH_Dp=mh_dp_orig; |
|
} |
|
|
|
if (MH_Verbose) oxprintf("x=%lf, y[0]=%lg\n",x,y[0]); |
result.x = x; |
result.x = x; |
result.rank = MH_RANK; |
result.rank = MH_RANK; |
result.y = (double *)mh_malloc(sizeof(double)*MH_RANK); /* todo, how to free it */ |
result.y = (double *)mh_malloc(sizeof(double)*MH_RANK); /* todo, how to free it */ |
Line 191 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
Line 264 struct MH_RESULT mh_rkmain(double x0,double y0[],doubl |
|
(result.sfpp)[0] = Df; |
(result.sfpp)[0] = Df; |
(result.sfpp)[1] = Gf; |
(result.sfpp)[1] = Gf; |
return result; |
return result; |
|
} |
|
|
|
|
|
/* |
|
rk4 MH_strategy==0; |
|
a-rk4 MH_strategy==1; adaptive |
|
a-rk4-m MH_strategy==2; adaptive and multiply |
|
*/ |
|
void mh_set_strategy(int s,double err[2]) { |
|
MH_strategy = s; |
|
if (err[0] >= 0.0) MH_abserr = err[0]; |
|
if (err[1] >= 0.0) MH_relerr = err[1]; |
} |
} |