/*
* heat1n-i-glsc.c -- é°çã¹ãã¼ã ã§ç±æ¹ç¨å¼ (Neumann BC) ã解ã
*
* èå°ã»å±±æ¬, å¾®åæ¹ç¨å¼ã¨è¨ç®æ©æ¼ç¿, 山海å (1991) 第11ç«
* p. 237 ã®ããã°ã©ã ãä¿®æ£ã»æ¡å¼µãããã®
*
C ** IMPLICIT FINITE DIFFERENCE METHOD **
C ** FOR HEAT EQUATION **
C nfunc : é¢æ°ã®çªå·ï¼5種é¡ã®é¢æ°ãç¨æãã¦ããï¼
C theta : ã¹ãã¼ã ã®ãã©ã¡ã¼ã¿ã¼
C N : åå²ã®æ°
C t : æå»
C tau : æéã®å»ã¿å¹
C Tmax : æå»ã®ä¸é
C h : 空éã®å»ã¿å¹
C AL,AD,AU : ä¿æ°è¡å
C u : DIMENSION FOR UNKNOWN FUNCTION
*
* ã³ã³ãã¤ã«: ccmg heat1n-i-glsc.c
* æåã³ã¼ãã«æ³¨æï¼ Windows ã§ã¯ qkc -ms heat1n-i-glsc.c ãå¿
è¦ãã
*
* ãã®ããã°ã©ã ã¯
* http://nalab.mind.meiji.ac.jp/~mk/program/
* ããå
¥æå¯è½
*/
#include
#include
#include
#ifndef G_DOUBLE
#define G_DOUBLE
#endif
#include
/* åå¨ç (math.h ã«ãã M_PI ã®å¤ãå©ç¨ãã
* ããã㯠double pi; ã¨ãã¦ãã©ãã㧠pi = 4.0 * atan(1.0); ã¨ä»£å
¥
* ã¾ã Visual C++ ã¨ãã§ã¯ M_PI ã¯ãªãã¨ãã話ãããã¾ãã
*/
const double pi = M_PI;
void trilu(int, double *, double *, double *);
void trisol(int, double *, double *, double *, double *);
double f(double, int);
void print100(int, double, double *);
void axis(double, double, double, double);
void print_parameters(double, double, double, double,
int, double, int,
double, double, double, double);
int main()
{
int N, nfunc, i, n, nMax;
double a, b, theta, h, Tmax, tau, c1, c2, c3, c4, lambda, t;
double *AL, *AD, *AU, *ff, *u;
double xleft, ybottom, xright, ytop;
/* ã°ã©ããæ¸ãæããæééé */
double dt;
/* ä½ã¹ãããããã«ã°ã©ããæ¸ãæããã */
int skip;
/* 以åæããã°ã©ããæ¶ããï¼ (0=No, 1=Yes) */
int erase_always = 0;
/* æ°å¤ã表示ããã? (0=No, 1=Yes) */
int print_numerical_data = 0;
/* */
double win_width, win_height, w_margin, h_margin;
/* åºéã®å·¦ç«¯ãå³ç«¯ */
a = 0.0;
b = 1.0;
/* å
¥å */
printf("å
¥åãã¦ä¸ãã : nfunc(1..5)=");
scanf("%d", &nfunc);
printf("å
¥åãã¦ä¸ãã : θ=");
scanf("%lf", &theta);
printf("å
¥åãã¦ä¸ãã : N=");
scanf("%d", &N);
printf("å
¥åãã¦ä¸ãã : λ=");
scanf("%lf", &lambda);
/* ãã¯ãã«ã®æºå */
AL = malloc((N + 1) * sizeof(double));
AD = malloc((N + 1) * sizeof(double));
AU = malloc((N + 1) * sizeof(double));
ff = malloc((N + 1) * sizeof(double));
u = malloc((N + 1) * sizeof(double));
if (AL == NULL || AD == NULL || AU == NULL || ff == NULL || u == NULL) {
fprintf(stderr, "ã¡ã¢ãªã¼ã確ä¿ã§ãã¾ããã§ããã\n");
exit(1);
}
/* å»ã¿å¹
ã®æ±ºå® */
h = (b - a) / N;
tau = lambda * h * h;
printf(" æéã®å»ã¿å¹
Ï= %g ã«ãªãã¾ããã\n", tau);
/* å
¥å */
printf("å
¥åãã¦ä¸ãã : æçµæå» Tmax=");
scanf("%lf", &Tmax);
printf("å
¥åãã¦ä¸ãã : ã°ã©ãæ¸ãæãæééé Ît=");
scanf("%lf", &dt);
skip = (int) rint(dt / tau);
/* skip ã 0 ã«ãªã£ã¦ããªãããã§ã㯠*/
if (skip == 0) {
fprintf(stderr, "Îtãå°ããããã®ã§ãÎt=Ï=%g ã«ãã¾ãã\n", tau);
skip = 1;
dt = tau;
}
/* ä¿æ°è¡åã®æºå */
c1 = - theta * lambda;
c2 = 1.0 + 2.0 * theta * lambda;
c3 = 1.0 - 2.0 * (1.0 - theta) * lambda;
c4 = (1.0 - theta) * lambda;
for (i = 1; i < N; i++) {
AL[i] = AU[i] = c1;
AD[i] = c2;
}
/* AL[0], AU[N] ã¯ä½¿ããªãã®ã§æ¬å½ã¯ä½ãããå¿
è¦ã¯ããã¾ãã */
AL[0] = 0; AD[0] = c2; AU[0] = 2 * c1;
AL[N] = 2 * c1; AD[N] = c2; AU[N] = 0;
/* åæå¤ */
for (i = 0; i <= N; i++)
u[i] = f(a + i * h, nfunc);
/* åºåï¼t=0ï¼ */
/* åºåï¼ããã§ã¯ç»é¢ã«æ°å¤ã表示ãããã¨ï¼ã¯ FORTRAN 㨠C ã§
ããªãç°ãªãã®ã§ãç´æ¥ã®ç¿»è¨³ã¯åºæ¥ãªããããããããã®ã§ã
print100 ã¨ããé¢æ°ã«ã¾ã¨ãã */
t = 0.0;
print100(N, t, u);
/* ã°ã©ãã£ãã¯ã¹ç»é¢ã®æºå -- ã¾ãç»é¢ã®ç¯å²ã決ãã¦ãã */
xleft = a - (b - a) / 10;
xright = b + (b - a) / 10;
ybottom = - 0.1;
ytop = 1.1;
/* ***************** ã°ã©ãã£ãã¯ã¹ã®æºå ***************** */
/* ã¡ã¿ãã¡ã¤ã«å㯠"HEAT1N",
* ã¦ã£ã³ãã¦ã®ãµã¤ãºã¯ã
横 win_width + 2 * w_margin, 縦 win_height + 2 * h_margin */
win_width = 150.0; win_height = 150.0; w_margin = 10.0; h_margin = 10.0;
g_init("HEAT1N", win_width + 2 * w_margin, win_height + 2 * h_margin);
/* ç»é¢ã¨ã¡ã¿ãã¡ã¤ã«ã®ä¸¡æ¹ã«è¨é²ãã */
g_device(G_BOTH);
/* 座æ¨ç³»ã®å®ç¾©: [-0.1,1.1]Ã[-0.1,1.1] ã¨ããéé åã表示ãã */
g_def_scale(0,
-0.1, 1.1, -0.1, 1.1,
w_margin, h_margin, win_width, win_height);
/* ç·ãäºç¨®é¡ç¨æãã */
g_def_line(0, G_BLACK, 0, G_LINE_SOLID);
g_def_line(1, G_BLACK, 0, G_LINE_DOTS);
/* 表示ããããã®æååã®å±æ§ãå®ç¾©ãã */
g_def_text(0, G_BLACK, 3);
/* å®ç¾©ãããã®ãé¸æãã */
g_sel_scale(0); g_sel_line(0); g_sel_text(0);
/* ã¿ã¤ãã«ã¨å
¥åãã©ã¡ã¼ã¿ã¼ã表示ãã */
print_parameters(xleft, ybottom, xright, ytop,
nfunc, theta, N,
lambda, tau, Tmax, t);
/* 座æ¨è»¸ã表示ãã */
g_sel_line(1);
g_move(-0.1, 0.0); g_plot(1.1, 0.0);
g_move(0.0, -0.1); g_plot(0.0, 1.1);
g_sel_line(0);
/* t=0 ã®ç¶æ
ã表示ãã */
g_move(0.0, u[0]);
for (i = 1; i <= N; i++)
g_plot(i * h, u[i]);
/* ä¿æ°è¡åã® LU å解 */
trilu(N + 1, AL, AD, AU);
/* ç¹°ãè¿ãè¨ç® */
nMax = (int) rint(Tmax / tau);
for (n = 1; n <= nMax; n++) {
/* é£ç«1次æ¹ç¨å¼ãä½ã£ã¦è§£ã */
for (i = 1; i < N; i++)
ff[i] = c3 * u[i] + c4 * (u[i - 1] + u[i + 1]);
ff[0] = c3 * u[0] + 2 * c4 * u[1];
ff[N] = c3 * u[N] + 2 * c4 * u[N - 1];
trisol(N + 1, AL, AD, AU, ff);
for (i = 0; i <= N; i++)
u[i] = ff[i];
/* æå» */
t = n * tau;
if (n % skip == 0) {
/* æ°å¤ãã¼ã¿ã®è¡¨ç¤º */
if (print_numerical_data)
print100(N, t, u);
/* 解ã®ã°ã©ããæã */
if (erase_always) {
/* ããã¾ã§æãããã®ãæ¶ãããã©ã¡ã¼ã¿ã¼ãå表示ãã */
g_cls();
print_parameters(xleft, ybottom, xright, ytop,
nfunc, theta, N, lambda, tau, Tmax, t);
}
g_move(0.0, u[0]);
for (i = 1; i <= N; i++)
g_plot(i * h, u[i]);
}
}
printf("ãã¦ã¹ã§ã¦ã£ã³ãã¦ãã¯ãªãã¯ãã¦ä¸ããã\n");
g_sleep(-1.0);
g_term();
return 0;
}
/**********************************************************/
/* ä¸é対è§è¡åã® LU å解 (pivoting ãªã) */
void trilu(int n, double *al, double *ad, double *au)
{
int i, nm1 = n - 1;
/* åé²æ¶å» (forward elimination) */
for (i = 0; i < nm1; i++) {
al[i + 1] /= ad[i];
ad[i + 1] -= au[i] * al[i + 1];
}
}
/* LU å解æ¸ã¿ã®ä¸é対è§è¡åãä¿æ°ã«æã¤ä¸é
æ¹ç¨å¼ã解ã */
void trisol(int n, double *al, double *ad, double *au, double *b)
{
int i, nm1 = n - 1;
/* åé²æ¶å» (forward elimination) */
for (i = 0; i < nm1; i++) b[i + 1] -= b[i] * al[i + 1];
/* å¾é代å
¥ (backward substitution) */
b[nm1] /= ad[nm1];
for (i = n - 2; i >= 0; i--) b[i] = (b[i] - au[i] * b[i + 1]) / ad[i];
}
/**********************************************************/
/* åææ¡ä»¶ãä¸ããé¢æ°ãè¤æ°ç»é²ãã¦çªå· nfunc ã§é¸æããã */
double f(double x, int nfunc)
{
/* f(x)=min(x,1-x)=1/2-|x-1/2| */
if (nfunc == 1) {
if (x <= 0.5)
return x;
else
return 1.0 - x;
}
/* f(x)=1 */
else if (nfunc == 2)
return 1.0;
else if (nfunc == 3)
return sin(pi * x);
/* f(x)= å¤ãªå½¢ããããã®(by M.Sakaue) */
else if (nfunc == 4) {
if (x <= 0.1)
return 5 * x;
else if (x <= 0.3)
return -2 * x + 0.7;
else if (x <= 0.5)
return 4.5 * x - 1.25;
else if (x <= 0.7)
return -x + 1.5;
else if (x <= 0.9)
return x + 0.1;
else
return -10 * x + 10.0;
}
/* ãã¯ãé対称ãªå½¢ããããã®(by M.Sakaue) */
else if (nfunc == 5) {
if (x <= 0.2)
return -x + 0.8;
else if (x <= 0.3)
return 4 * x - 0.2;
else if (x <= 0.4)
return -4 * x + 2.2;
else if (x <= 0.7)
return -x + 1.0;
else if (x <= 0.8)
return 4 * x - 2.6;
else
return -x + 1.5;
} else
return 0;
}
/**********************************************************/
/* é
å u[] ã®å
容(u[0],u[1],...,u[n])ãä¸è¡ 5 åãã¤è¡¨ç¤ºããã */
void print100(int N, double t, double *u)
{
int i;
printf("T= %12.4e\n", t);
for (i = 0; i < 5; i++)
printf(" I u(i) ");
printf("\n");
for (i = 0; i <= N; i++) {
printf("%3d%12.4e ", i, u[i]);
if (i % 5 == 4)
printf("\n");
}
printf("\n");
}
/**********************************************************/
/* ã¦ã£ã³ãã¦ã«åº§æ¨è»¸ã表示ãã */
void axis(double xleft, double ybottom, double xright, double ytop)
{
g_sel_line(1);
g_move(xleft, 0.0); g_plot(xright, 0.0);
g_move(0.0, ybottom); g_plot(0.0, ytop);
g_sel_line(0);
}
/* ãã©ã¡ã¼ã¿ã¼ã®å¤çãã¦ã£ã³ãã¦ã«è¡¨ç¤ºãã */
void print_parameters(double xleft, double ybottom, double xright, double ytop,
int nfunc, double theta, int N,
double lambda, double tau, double Tmax, double t)
{
char message[80];
axis(xleft, ybottom, xright, ytop);
g_text(30.0, 30.0, "heat equation, ux(0,t)=ux(1,t)=0");
snprintf(message, sizeof(message),
"nfunc=%d, theta=%g, N=%d, lambda=%g, tau=%g, Tmax=%g",
nfunc, theta, N, lambda, tau, Tmax);
g_text(30.0, 60.0, message);
if (t != 0.0) {
snprintf(message, sizeof(message), "t = %g", t);
g_text(30.0, 90.0, message);
}
}