C言語プログラムの不明点

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
popgon

C言語プログラムの不明点

#1

投稿記事 by popgon » 13年前

作っているプログラム概要
・3次元空間に引力、斥力を他者に及ぼす点を配置し、その中を質点(持っている力ー1)が動き回りどのような動きをするか確認するプログラム

困っていること
・動き回れる質点を現在の1個から複数にしたいが計算結果がすべて0になりきちんとした結果が得られないこと
・今は無限の3次元空間となっているが有限の3次元空間にしたいができないこと (したい大きさ16*16*16)
・現在は手入力で質点等のデータを入れているがこれを疑似乱数で自動入力方式にしたいこと

コード:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <time.h>
#define DT 0.001
#define TIMELIMIT 20.0
#define R 0.1
#define BUFSIZE 256
#define N 256
#define M 3
#define LIMIT 2
#define ULONG_MAX 50

struct coordinate {
	double x;/*x座標*/
	double y;/*y座標*/
	double z;/*z座標*/
};

struct charge {
	struct coordinate qxy;/*電荷の位置*/
	double q;/*電荷*/
	struct coordinate v,x;
};

int getdouble(double *x);/*実数の読み込み*/
int inputq(struct charge qi[]);/*電荷入力*/
int inputn(struct charge qp[]);
int main()
{
	struct coordinate v,x;/*質点の速度と位置*/
	struct charge qi[N];
	struct charge qp[M];
	int nofq;
	int nofn;
	double t=0;
	double h=DT;
	double rx,ry,rz,r,rmin;
	int i;
	clock_t start,end;/*処理時間計測関数*/
	//入力終了
	nofn=inputn(qp);
	nofq=inputq(qi);

	printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\n",t,x.x,x.y,x.z,v.x,v.y,v.z);
	start = clock();
	printf("開始時間:%f\n",start);
	while(t<=TIMELIMIT){
		t+=h;
	rmin=DBL_MAX;
	for(i=0;i<nofq;++i){
		rx=qi[i].qxy.x-x.x;//位置x座標計算
		ry=qi[i].qxy.y-x.y;//位置y座標計算
		rz=qi[i].qxy.z-x.z;//位置z座標計算
		r=sqrt(rx*rx+ry*ry+rz*rz);
		if(r<rmin) rmin=r;
		qp[i].v.x+=(rx/r/r/r*qi[i].q)*h;//速度x座標計算
		qp[i].v.y+=(ry/r/r/r*qi[i].q)*h;//速度y座標計算
		qp[i].v.z+=(rz/r/r/r*qi[i].q)*h;//速度z座標計算
	}
	end = clock();
	printf("処理時間=%f\n",(double)(end-start)/CLOCKS_PER_SEC);/*処理時間出力*/
	x.x+=v.x*h;
	x.y+=v.y*h;
	x.z+=v.z*h;
	printf("刻み時間=%f\t\n質点の位置(%f\t,%f\t,%f)\n質点の速度(%f\t,%f\t,%f)\n",t,x.x,x.y,x.z,v.x,v.y,v.z);
	
	if(rmin<R) break;
	}
	return 0;
}

 
int inputq(struct charge qi[])
{
	int i;
	for(i=0;i<N;++i){
		fprintf(stderr,"電荷%d\n",i);
		fprintf(stderr,"電荷の配置箇所qxy.x\n");
		if(getdouble(&qi[i].qxy.x)==EOF)break;
		fprintf(stderr,"電荷の配置箇所qxy.y\n");
		if(getdouble(&qi[i].qxy.y)==EOF)break;
		fprintf(stderr,"電荷の配置箇所qxy.z\n");
		if(getdouble(&qi[i].qxy.z)==EOF)break;
		fprintf(stderr,"電荷の値q\n");
		if(getdouble(&qi[i].q)==EOF)break;
	}
	return i;
}
int inputn(struct charge qp[])
{
	int i;
	for(i=0;i<M;i++){
		//入力開始
		fprintf(stderr,"初速度%dv0x\n",i);
		if(getdouble(&qp[i].v.x)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0y\n",i);
		if(getdouble(&qp[i].v.y)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0z\n",i);
		if(getdouble(&qp[i].v.z)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.x\n",i);
		if(getdouble(&qp[i].x.x)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.y\n",i);
		if(getdouble(&qp[i].x.y)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.z\n",i);
		if(getdouble(&qp[i].x.z)==EOF)exit(1);
	}
	return i;
}



int getdouble(double *x)
{
	char linebuf[BUFSIZE];
	int result=0;

	if(fgets(linebuf,BUFSIZE,stdin)!=NULL){
		if(sscanf(linebuf,"%lf",x)<=0)
			result=EOF;
	}else{
		result=EOF;
	}
	return result ;
}
と現在できているのはここまでです。ぜひ解決のためにみなさんの助力をお借りしたいです。どうかよろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#2

投稿記事 by softya(ソフト屋) » 13年前

データ入力が大変なので、入力データをテキストにして貼りつけて頂けますか?
リダイレクトで入力したいと思います。

あと struct charge にあるstruct coordinate v,x;が名前がわかりづらいのでちゃんとした名前をつけてもらえますか。
たぶん、この構造体には必要のないものなんじゃないかと思います。

動きまわる質点にかかわるのが、struct coordinate v,x;で struct charge は「引力、斥力を他者に及ぼす点」では無いでしょうか?

[追記]
あと質点って電荷を持ってるんですよね?
(持っている力ー1)
これのことです?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

non
記事: 1097
登録日時: 13年前

Re: C言語プログラムの不明点

#3

投稿記事 by non » 13年前

46行  printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\n",t,x.x,x.y,x.z,v.x,v.y,v.z);
で何を表示したいのかわかりませんが、
32行 struct coordinate v,x;/*質点の速度と位置*/
に初期値を与えていないので、意味が分かりません。
私が、思うに、元の質点が1個だったときに、32行に質点を入れていたのでしょうね。それを複数にするために、
43行 nofn=inputn(qp);
で、3つの質点を与えようとしているのではないか?
そのあとの、座標計算においても、それがごちゃまぜになってますね。

しかし、そうなると、構造体の作り方に考慮した方がいいですね。
電荷用の構造体と、質点用の構造体は別にすべきです。

私の想像で、話していますので、違えば指摘してください。
non

popgon

Re: C言語プログラムの不明点

#4

投稿記事 by popgon » 13年前

>>softya(ソフト屋)さん
質点1 初速度(5,3,4) 位置(10,6,4) 
質点2 初速度(2,10,5)位置(15,5,11)
質点3 初速度(5,3,10)位置(4,1,1)

電荷(配置は2個まで)
電荷1 配置個所(10,10,5)
電荷2 配置個所(3,6,10)

で実行したいと思っています。
質点が持っている電荷は(-1)として作っています。
あとstruct coordinateは質点を複数にしたときに入力時=にならないといわれ苦し紛れに付け加えたので正直必要のないものなのかもしれません。
あとその通りでstrcut chargeが引力斥力を他者に及ぼす点です。
構造体の名前を変えるべきでした。

>>nonさん
46行はもともと質点の数が1個だったときに質点の位置などを入れて出力するためのものでした。
いまのその状態ではたぶん機能していませんね。すみませんでした。

32行ももともと1個だった質点入力用のために入れたものでした。質点1個のときは46行の上らへんに質点1個のデータ入力の文を入れていました。
確かに構造体を変えるべきですね。ご指摘ありがとうございます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#5

投稿記事 by softya(ソフト屋) » 13年前

今までのアドバイスを元にプログラムをも書きなおしてらえますか。
書き直すため分からない事があれば質問してくださいね。

ポイント
・「動きまわる質点」と「引力斥力を他者に及ぼす点」は別の構造体にする。
・「動きまわる質点」と「引力斥力を他者に及ぼす点」は別の配列である。
・名前をわかりやすくつける。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

popgon

Re: C言語プログラムの不明点

#6

投稿記事 by popgon » 13年前

コード:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <time.h>
#define DT 0.001
#define TIMELIMIT 20.0
#define R 0.1
#define BUFSIZE 256
#define N 256
#define M 3
#define LIMIT 2
#define ULONG_MAX 50

struct coordinate {
	double x;/*x座標*/
	double y;/*y座標*/
	double z;/*z座標*/
};

struct charge {
	struct coordinate qxy;/*電荷の位置*/
	double q;/*電荷*/
	
};

struct material {
	struct coordinate v,x;/*質点の速度と位置*/
};

int getdouble(double *x);/*実数の読み込み*/
int inputq(struct charge qi[]);/*電荷入力*/
int inputn(struct material qp[]);/*質点入力*/
int main()
{
	struct coordinate v,x;/*質点の速度と位置*/
	struct charge qi[N];
	struct material qp[M];
	int nofq;
	int nofn;
	double t=0;
	double h=DT;
	double rx,ry,rz,r,rmin;
	int i,j;
	clock_t start,end;/*処理時間計測関数*/
	/*for(i=0;i<3;++i){
		fprintf(stderr,"初速度%dv0x\n",i);
		if(getdouble(&v.x)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0y\n",i);
		if(getdouble(&v.y)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0z\n",i);
		if(getdouble(&v.z)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.x\n",i);
		if(getdouble(&x.x)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.y\n",i);
		if(getdouble(&x.y)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.z\n",i);
		if(getdouble(&x.z)==EOF)exit(1);
	}*/
	nofn=inputn(qp);
	nofq=inputq(qi);
	//printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\n",t,x.x,x.y,x.z,v.x,v.y,v.z);
	start = clock();
	printf("開始時間:%f\n",start);
	while(t<=TIMELIMIT){
		t+=h;
		rmin=DBL_MAX;
		for(j=0;j<nofn;j++){
			for(i=0;i<nofq;++i){
				rx=qi[i].qxy.x-qp[j].x.x;//位置x座標計算
				ry=qi[i].qxy.y-qp[j].x.y;//位置y座標計算
				rz=qi[i].qxy.z-qp[j].x.z;//位置z座標計算
				r=sqrt(rx*rx+ry*ry+rz*rz);
				if(r<rmin) rmin=r;
				qp[j].v.x+=(rx/r/r/r*qi[i].q)*h;//速度x座標計算
				qp[j].v.y+=(ry/r/r/r*qi[i].q)*h;//速度y座標計算
				qp[j].v.z+=(rz/r/r/r*qi[i].q)*h;//速度z座標計算
			}
		end = clock();
		printf("処理時間=%f\n",(double)(end-start)/CLOCKS_PER_SEC);/*処理時間出力*/
		qp[j].x.x+=qp[j].v.x*h;
		qp[j].x.y+=qp[j].v.y*h;
		qp[j].x.z+=qp[j].v.z*h;
		printf("刻み時間=%f\t\n質点の位置(%f\t,%f\t,%f)\n質点の速度(%f\t,%f\t,%f)\n",t,qp[j].x.x,qp[j].x.y,qp[j].x.z,qp[j].v.x,qp[j].v.y,qp[j].v.z);//質点の現在地等出力
		}
	
		if(rmin<R) break;
	}
	return 0;
}


/*電荷の値入力*/
int inputq(struct charge qi[])
{
	int i;
	for(i=0;i<N;++i){
		fprintf(stderr,"電荷%d\n",i);
		fprintf(stderr,"電荷の配置箇所qxy.x\n");
		if(getdouble(&qi[i].qxy.x)==EOF)break;
		fprintf(stderr,"電荷の配置箇所qxy.y\n");
		if(getdouble(&qi[i].qxy.y)==EOF)break;
		fprintf(stderr,"電荷の配置箇所qxy.z\n");
		if(getdouble(&qi[i].qxy.z)==EOF)break;
		fprintf(stderr,"電荷の値q\n");
		if(getdouble(&qi[i].q)==EOF)break;
	}
	return i;
}

/*質点の値入力*/
int inputn(struct material qp[])
{
	int i;
	struct coordinate v,x;
	for(i=0;i<3;++i){
		fprintf(stderr,"初速度%dv0x\n",i);
		if(getdouble(&qp[i].v.x)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0y\n",i);
		if(getdouble(&qp[i].v.y)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0z\n",i);
		if(getdouble(&qp[i].v.z)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.x\n",i);
		if(getdouble(&qp[i].x.x)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.y\n",i);
		if(getdouble(&qp[i].x.y)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.z\n",i);
		if(getdouble(&qp[i].x.z)==EOF)exit(1);
	}
	return i;
}


int getdouble(double *x)
{
	char linebuf[BUFSIZE];
	int result=0;

	if(fgets(linebuf,BUFSIZE,stdin)!=NULL){
		if(sscanf(linebuf,"%lf",x)<=0)
			result=EOF;
	}else{
		result=EOF;
	}
	return result ;
}
とこのように書きなおしてみたのですが…一応複数の質点で計算結果を行うことに成功?したのかなと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#7

投稿記事 by softya(ソフト屋) » 13年前

・動き回れる質点を現在の1個から複数にしたいが計算結果がすべて0になりきちんとした結果が得られないこと
popgon さんが書きました:とこのように書きなおしてみたのですが…一応複数の質点で計算結果を行うことに成功?したのかなと思います。
これの検証はご自分で行ってください。
グラフにプロットするなど視覚的に確認したほうが良いかもしれませんが。

ちなみに頂いた質点・電荷データの内、電荷データの電荷値がなかったので勝手に追加しました。

・今は無限の3次元空間となっているが有限の3次元空間にしたいができないこと (したい大きさ16*16*16)

これで疑問なのは質点が空間外に出ようとしたら超常的な力で反射するのか、圏外に出たら消滅するのか仕様が不明確な点です。
そもそも何のために「有限の3次元空間」にしたいのかがわかりません。

・現在は手入力で質点等のデータを入れているがこれを疑似乱数で自動入力方式にしたいこと

C言語の標準乱数で良いのでしょうか?
あと各数値の範囲とあってはいけない条件を決めてください。電荷は重なっていけない等。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: C言語プログラムの不明点

#8

投稿記事 by GRAM » 13年前

やりたいことは最後のプログラムで大体わかりますが、
質点というのは少なくとも「クーロン定数kに対して、kの質量をもつ」として計算するようですね。
「その中を質点(持っている力ー1)」
この表現がいまいちわかりませんが、上のプログラムを見るかぎりでは
質点の性質として「単位電荷をもつ点として静電気力を受けるが、自分は静電気力を与えない」という性質があるように思えます。
もしくは「質点の持つ電荷は固定点の電荷よりもはるかに小さく無視できる」という条件が与えられているかどちらかでしょう。

もしも、質点が無視できないほどに電荷をもっていて、ほかの質点にも静電気力を及ぼすのならば、上のプログラムは誤りだといえます。
十分に狭い空間でのシミュレーションであれば、固定点の電荷の大きさ次第でしょう

追記:
あ、乱数使って決めるなら、質点の初速度を速くしすぎないように気を付けたり、電荷の値を小さくしすぎたり大きくしすぎたりしないように気を付けたほうがいいでしょう。
「物理的な」シミュレーションをするのであらば、上に書いた近似が成り立たなくなることや、ガウス求積の不正確さが増大しますので。

ちなみにもし近似を取っ払って「質点間の力の相互作用」を考えるのなら僕は質点と固定点の構造体は一緒にしてしまいますね。
固定点はあくまでも「質量無限大の点」にすぎないわけですし。あくまでも参考ですけれど。
最後に編集したユーザー GRAM on 2011年8月23日(火) 12:42 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#9

投稿記事 by softya(ソフト屋) » 13年前

「お互いが及ぼす静電気力に対して電荷自身の質量が膨大なので、単位時間あたりの影響は無視出来る。」って解釈はどうでしょう?

[追記]
あるいは超常的な力で空間に固定されている電荷だと言うことにして計算をする問題である。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
GRAM
記事: 164
登録日時: 13年前
住所: 大阪

Re: C言語プログラムの不明点

#10

投稿記事 by GRAM » 13年前

softya(ソフト屋) さんが書きました:「お互いが及ぼす静電気力に対して電荷自身の質量が膨大なので、単位時間あたりの影響は無視出来る。」って解釈はどうでしょう?
十分に狭い空間で、かつ質点が接近しないのであれば、
質点の質量は関係ありません。あくまで質点のもつ-1qの電荷の大きさが空間に固定されている電荷に対して無視できるのか否かが問題なのです。
上のプログラムには単位がないので私には何とも言えませんが、たとえば固定された電荷が10000qを持っていたとしましょう。
この時質点同士の距離が、固定された電荷と同じくらい離れているという仮定の下では、ほかの質点からの力は無視できるほど小さくなります。
(もちろん質点同士が接近すると力の相互作用は無視できなくなるので過程は成り立たなくなります。また広い空間を考えるのなら、固定電荷から十分に離れたときのほかの電荷からの電場が無視できなくなります)

接近を考えるのならば上のプログラムは
「単位電荷をもつ点として静電気力を受けるが、自分は静電気力を与えない」としなければどうしようもないのです。
現実に則したシミュレーションをするとなると、質点同士の相互作用を考えざるを得ません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#11

投稿記事 by softya(ソフト屋) » 13年前

すいません用語がややこしいくて(汗)
固定点ではない、移動する質点同士の相互作用のことですね。
確かに無視したらシミュレーション的にまずいですね(今のプログラムは無視されています)。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

popgon

Re: C言語プログラムの不明点

#12

投稿記事 by popgon » 13年前

>>softya(ソフト屋)さん
説明不足でした。
有限空間とした場合、計算で空間の範囲外にいってしまった時、跳ね返りを計算し、その動きを実装したいとも思っています。
ちなみに有限空間にしたい理由は、並列処理を行うために、空間分割し、ノードに1つずつ割り付けたいと考えているからです。

乱数については、

コード:

#include <stdio.h>
#include <stdlib.h>

#define LIMIT 50

int main()
{
	unsigned long r;
	int i;
	r=10;

	for(i=0;i<LIMIT;++i){
		r=1664525L*r+1013904223L;
		printf("%lu\n",r%16);
	}
	return 0;
}
のような疑似乱数で値を与えたいと思っています。
ただその時に、質点と質点は重なっても構わないが、質点と電荷は重ならないようにしたいです。


>>GRAMさん
確かに質点を1個の場合だと、配置された電荷が複数でも質点は1個だけなので質点同士の相互作用を考えずに作ってしまっていました。
複数になる場合はGRAMさんのおっしゃる通り相互作用を考えなければいけませんね。
今から付け加えてみようと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#13

投稿記事 by softya(ソフト屋) » 13年前

視覚化してみたかったので、プログラムそのままでDXライブラリで視覚化してみました。

コード:

#include "DxLib.h"

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <time.h>
#define DT 0.01
#define TIMELIMIT 20.0
#define R 0.1
#define BUFSIZE 256
#define N 256
#define M 3
#define LIMIT 2
#define ULONG_MAX 50

struct coordinate {
	double x;/*x座標*/
	double y;/*y座標*/
	double z;/*z座標*/
};

struct charge {
	struct coordinate qxy;/*電荷の位置*/
	double q;/*電荷*/

};

struct material {
	struct coordinate v,x;/*質点の速度と位置*/
};

int getdouble(double *x);/*実数の読み込み*/
int inputq(struct charge qi[]);/*電荷入力*/
int inputn(struct material qp[]);/*質点入力*/


double t=0;
struct charge qi[N];
struct material qp[M];
int nofq;
int nofn;
double h=DT;
FILE *fp;

void main_input()
{
	//    struct coordinate v,x;/*質点の速度と位置*/
	/*for(i=0;i<3;++i){
	fprintf(stderr,"初速度%dv0x\n",i);
	if(getdouble(&v.x)==EOF)exit(1);
	fprintf(stderr,"初速度%dv0y\n",i);
	if(getdouble(&v.y)==EOF)exit(1);
	fprintf(stderr,"初速度%dv0z\n",i);
	if(getdouble(&v.z)==EOF)exit(1);
	fprintf(stderr,"初期位置%dx.x\n",i);
	if(getdouble(&x.x)==EOF)exit(1);
	fprintf(stderr,"初期位置%dx.y\n",i);
	if(getdouble(&x.y)==EOF)exit(1);
	fprintf(stderr,"初期位置%dx.z\n",i);
	if(getdouble(&x.z)==EOF)exit(1);
	}*/
	fp = fopen("input.txt","rt");
	nofn=inputn(qp);
	nofq=inputq(qi);
	fclose(fp);
	//printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\n",t,x.x,x.y,x.z,v.x,v.y,v.z);
}

void main_loop()
{
	double rx,ry,rz,r,rmin;
	int i,j;
	clock_t start,end;/*処理時間計測関数*/
	start = clock();
	printf("開始時間:%f\n",start);

	//    while(t<=TIMELIMIT){
	t+=h;
	rmin=DBL_MAX;
	for(j=0;j<nofn;j++){
		for(i=0;i<nofq;++i){
			rx=qi[i].qxy.x-qp[j].x.x;//位置x座標計算
			ry=qi[i].qxy.y-qp[j].x.y;//位置y座標計算
			rz=qi[i].qxy.z-qp[j].x.z;//位置z座標計算
			r=sqrt(rx*rx+ry*ry+rz*rz);
			if(r<rmin) rmin=r;
			qp[j].v.x+=(rx/r/r/r*qi[i].q)*h;//速度x座標計算
			qp[j].v.y+=(ry/r/r/r*qi[i].q)*h;//速度y座標計算
			qp[j].v.z+=(rz/r/r/r*qi[i].q)*h;//速度z座標計算
		}
		end = clock();
		printf("処理時間=%f\n",(double)(end-start)/CLOCKS_PER_SEC);/*処理時間出力*/
		qp[j].x.x+=qp[j].v.x*h;
		qp[j].x.y+=qp[j].v.y*h;
		qp[j].x.z+=qp[j].v.z*h;
		printf("刻み時間=%f\t\n質点の位置(%f\t,%f\t,%f)\n質点の速度(%f\t,%f\t,%f)\n",t,qp[j].x.x,qp[j].x.y,qp[j].x.z,qp[j].v.x,qp[j].v.y,qp[j].v.z);//質点の現在地等出力
	}

	if(rmin<R) return;

	//--------------------------------------
	//	3D		
	//--------------------------------------

	DrawBox(0,0,640,480,GetColor(255,255,255),TRUE);

	//	カメラをセット
	SetCameraPositionAndTargetAndUpVec( VGet(20.0f,20.0f,-20.0f), VGet(10.0f,10.0f,10.0f), VGet( 0.0f, 20.0f, 0.0f ) );

	//	軸を描く
	DrawCone3D( VGet(20.0f,0.0f,0.0f), VGet(0.0f,0.0f,0.0f), 0.5f, 30, GetColor(255,0,0), GetColor(255,255,255), TRUE );
	DrawCone3D( VGet(0.0f,20.0f,0.0f), VGet(0.0f,0.0f,0.0f), 0.5f, 30, GetColor(0,255,0), GetColor(255,255,255), TRUE );
	DrawCone3D( VGet(0.0f,0.0f,20.0f), VGet(0.0f,0.0f,0.0f), 0.5f, 30, GetColor(0,255,255), GetColor(255,255,255), TRUE );

	//	電荷をプロット
	for(i=0;i<nofq;++i){
		float r = qi[i].q / 1000.0f;
		if( qi[i].q < 0 ) {
			DrawSphere3D( VGet(qi[i].qxy.x,qi[i].qxy.y,qi[i].qxy.z), r, 20, GetColor(100,100,255), GetColor(255,255,255), TRUE );
		} else {
			DrawSphere3D( VGet(qi[i].qxy.x,qi[i].qxy.y,qi[i].qxy.z), r, 20, GetColor(255,100,100), GetColor(255,255,255), TRUE );
		}
	}

	//	質点をプロット
	for(j=0;j<nofn;j++){
		DrawSphere3D( VGet(qp[j].x.x,qp[j].x.y,qp[j].x.z), 0.3f, 20, GetColor(100,255,100), GetColor(255,255,255), TRUE );
		//	ベクトルを書き加える。
		DrawCone3D( VGet(qp[j].x.x+qp[j].v.x,qp[j].x.y+qp[j].v.y,qp[j].x.z+qp[j].v.z), VGet(qp[j].x.x,qp[j].x.y,qp[j].x.z), 0.1f, 30, GetColor(0,255,0), GetColor(255,255,255), TRUE );
	}

	//	  }
	//    return 0;
}


/*電荷の値入力*/
int inputq(struct charge qi[])
{
	int i;
	for(i=0;i<N;++i){
		fprintf(stderr,"電荷%d\n",i);
		fprintf(stderr,"電荷の配置箇所qxy.x\n");
		if(getdouble(&qi[i].qxy.x)==EOF)break;
		fprintf(stderr,"電荷の配置箇所qxy.y\n");
		if(getdouble(&qi[i].qxy.y)==EOF)break;
		fprintf(stderr,"電荷の配置箇所qxy.z\n");
		if(getdouble(&qi[i].qxy.z)==EOF)break;
		fprintf(stderr,"電荷の値q\n");
		if(getdouble(&qi[i].q)==EOF)break;
	}
	return i;
}

/*質点の値入力*/
int inputn(struct material qp[])
{
	int i;
	//    struct coordinate v,x;
	for(i=0;i<3;++i){
		fprintf(stderr,"初速度%dv0x\n",i);
		if(getdouble(&qp[i].v.x)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0y\n",i);
		if(getdouble(&qp[i].v.y)==EOF)exit(1);
		fprintf(stderr,"初速度%dv0z\n",i);
		if(getdouble(&qp[i].v.z)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.x\n",i);
		if(getdouble(&qp[i].x.x)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.y\n",i);
		if(getdouble(&qp[i].x.y)==EOF)exit(1);
		fprintf(stderr,"初期位置%dx.z\n",i);
		if(getdouble(&qp[i].x.z)==EOF)exit(1);
	}
	return i;
}


int getdouble(double *x)
{
	char linebuf[BUFSIZE];
	int result=0;

	if(fgets(linebuf,BUFSIZE,fp)!=NULL){
		if(sscanf(linebuf,"%lf",x)<=0)
			result=EOF;
	}else{
		result=EOF;
	}
	return result ;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode( TRUE );
	SetDrawScreen( DX_SCREEN_BACK );

	if( DxLib_Init() == -1 ) 
	{
		return -1;
	} 
	main_input();

	SetCameraNearFar( 1.0f, 200.0f ) ;

	// Zバッファを有効にする
	SetUseZBuffer3D( TRUE ) ;

	// Zバッファへの書き込みを有効にする
	SetWriteZBuffer3D( TRUE ) ;


	while( CheckHitKey(KEY_INPUT_ESCAPE) == 0 )
	{
		if( ProcessMessage() == -1 ) break;

		//画面をクリア
		ClearDrawScreen();

		main_loop();

		//裏画面を表画面へ
		ScreenFlip();
	}

	DxLib_End();

	return(0) ;
}
ちなみにinput.txtの中身

コード:

5
3
4
10
6
4
2
10
5
15
5
11
5
3
10
4
1
1
10
15
5
-500
3
6
10
1000
動きを面白くするために強烈な電荷を与えています。
添付ファイル
電荷.png
電荷.png (56.88 KiB) 閲覧数: 5075 回
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#14

投稿記事 by softya(ソフト屋) » 13年前

popgon さんが書きました:説明不足でした。
有限空間とした場合、計算で空間の範囲外にいってしまった時、跳ね返りを計算し、その動きを実装したいとも思っています。

単に反射したければ、外へ出た瞬間にベクトルの符号を逆転すれば良いと思います。
跳ね返りとすれば衝突した平面に合わせて特定のベクトルの符号を判定します。
ただ、本当にそれで良いのですか?
地理シミュレーションとしては気持ち悪い気が。
popgon さんが書きました: ちなみに有限空間にしたい理由は、並列処理を行うために、空間分割し、ノードに1つずつ割り付けたいと考えているからです。
空間分割ってのがピンと来ませんが、1つのノードに1つに質点って意味でしょうか?
それとも立方体グリッド毎に、そこに含まれる質点全部ってことでしょうか?
popgon さんが書きました:のような疑似乱数で値を与えたいと思っています。
ただその時に、質点と質点は重なっても構わないが、質点と電荷は重ならないようにしたいです。
その乱数の方法だとスタート時に同じ値になるので乱数の種を何らかの形で毎回変化しないとランダムではありません。
それと質点の初速の上限とか、電荷のq値の上限とか、電荷の近よっても良い距離など明確に決めないとプログラムとして問題があると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

popgon

Re: C言語プログラムの不明点

#15

投稿記事 by popgon » 12年前

>>softya(ソフト屋)さん
シミュレーションとしては空間を作成し跳ね返りをつけると確かに気持ち悪くなるかもしれません。
ただ空間を限定しない場合、質点が遠くにいきすぎて見えなくなってしまうので、見た時にわかりやすくしたいという思惑もありました。
それをすると本当のシミュレーションとしては失格かもしれませんね。

空間分割ですが、全体を立方体で分割し、その空間に含まれる質点を、空間を割り付けたノードで計算するという方法をしたいと思っています。

疑似乱数は確かに一回テストしてみたところ初期値が一緒だと毎回同じ配列になりますね。
今回のプログラムでは、できれば質点は同じ値で何回も施行できる方が都合がいいのでこれを使用しようと思いました。
ただsoftya(ソフト屋)さんのおっしゃるように初速の上限や電荷の値の上限を決めないとおかしなりますね。
少し考えてみようと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C言語プログラムの不明点

#16

投稿記事 by softya(ソフト屋) » 12年前

popgon さんが書きました:>>softya(ソフト屋)さん
シミュレーションとしては空間を作成し跳ね返りをつけると確かに気持ち悪くなるかもしれません。
ただ空間を限定しない場合、質点が遠くにいきすぎて見えなくなってしまうので、見た時にわかりやすくしたいという思惑もありました。
それをすると本当のシミュレーションとしては失格かもしれませんね。
その質点は消滅して、新たに質点をランダム発生するってもひとつの手です。
popgon さんが書きました: 空間分割ですが、全体を立方体で分割し、その空間に含まれる質点を、空間を割り付けたノードで計算するという方法をしたいと思っています。
理解できました。ただ、隣り合う空間の影響の計算はどうされるおつもりですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

popgon

Re: C言語プログラムの不明点

#17

投稿記事 by popgon » 12年前

>>softya(ソフト屋) さん
確かに一回枠外に飛び出したら消えて最初からというのがよさそうですね。
その方向で作成してみようと思います。

確かに隣り合う空間の影響は無視できないと思います。
その場合常に相互通信で距離を測りながら影響も考えることが必要ですよね。
たぶんそうすると計算量も膨大になりますよね…。実際今それをどうしようか考えているところだったんです。

popgon

Re: C言語プログラムの不明点

#18

投稿記事 by popgon » 12年前

最終的には質点でノード各自に分けてやることにしました。

空間は有限じゃなくとりあえず無限でやります。

今までご教授してくださった方々ありがとうございました。

また質問させてもらうことがあると思いますが、その時はよろしくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る