Esempio n. 1
0
static bool AddLinearSystem_Diffusion_P1b(
		double rho, double alpha, double source,
		double gamma, double dt,
		CLinearSystem_Field& ls, 
		unsigned int id_field_val, const CFieldWorld& world,
		unsigned int id_ea )
{	
//	std::cout << "Diffusion2D Tri P1b" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c = field_val.GetElemSeg(id_ea,CORNER,true,world);
	const CElemAry::CElemSeg& es_b = field_val.GetElemSeg(id_ea,BUBBLE,true,world);

	const unsigned int nno_c = 3;
	const unsigned int nno_b = 1;
	const unsigned int ndim = 2;

	unsigned int no_c[nno_c];
	unsigned int no_b;

	double val_c[nno_c], val_b;
	double vval_c[nno_c], vval_b;
	double coord_c[nno_c][ndim];
				
	double dldx[nno_c][ndim];
	double const_term[nno_c];

	double eCmat_cc[nno_c][nno_c], eCmat_cb[nno_c], eCmat_bc[nno_c], eCmat_bb;
	double eMmat_cc[nno_c][nno_c], eMmat_cb[nno_c], eMmat_bc[nno_c], eMmat_bb;
	double eqf_out_c[nno_c], eqf_out_b;
	double eqf_in_c[nno_c], eqf_in_b;

	double emat_cc[nno_c][nno_c], emat_cb[nno_c], emat_bc[nno_c], emat_bb;
	double eres_c[nno_c], eres_b;	// 要素節点等価内力、外力、残差ベクトル

	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(id_field_val,CORNER, world);
	CMatDia_BlkCrs& mat_bb = ls.GetMatrix(id_field_val,BUBBLE, world);
	CMat_BlkCrs&    mat_cb = ls.GetMatrix(id_field_val,CORNER, id_field_val, BUBBLE, world);
	CMat_BlkCrs&    mat_bc = ls.GetMatrix(id_field_val,BUBBLE, id_field_val, CORNER, world);
	////////////////
	CVector_Blk& res_c = ls.GetResidual(id_field_val,CORNER, world);
	CVector_Blk& res_b = ls.GetResidual(id_field_val,BUBBLE, world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true,world,VALUE);//na_c_val.GetSeg(id_ns_c_val);
	const CNodeAry::CNodeSeg& ns_c_vval = field_val.GetNodeSeg(CORNER,true,world,VELOCITY);//na_c_val.GetSeg(id_ns_c_vval);
	const CNodeAry::CNodeSeg& ns_b_val = field_val.GetNodeSeg(BUBBLE,true,world,VALUE);//na_b_val.GetSeg(id_ns_b_val);
	const CNodeAry::CNodeSeg& ns_b_vval = field_val.GetNodeSeg(BUBBLE,true,world,VELOCITY);//na_b_val.GetSeg(id_ns_b_vval);
	const CNodeAry::CNodeSeg& ns_c_co = field_val.GetNodeSeg(CORNER,false,world,VALUE);//na_c_val.GetSeg(id_ns_c_co);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++){
		// 要素配列から節点セグメントの節点番号を取り出す
		es_c.GetNodes(ielem,no_c);
		es_b.GetNodes(ielem,&no_b);
		// 節点の値を取ってくる
		for(unsigned int inoes=0;inoes<nno_c;inoes++){
			ns_c_co.GetValue(no_c[inoes],coord_c[inoes]);
			ns_c_val.GetValue(no_c[inoes],&val_c[inoes]);
			ns_c_vval.GetValue(no_c[inoes],&vval_c[inoes]);
		}
		ns_b_val.GetValue(no_b,&val_b);
		ns_b_vval.GetValue(no_b,&vval_b);

		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);
		{	// 要素剛性行列を作る
			double vc_b[4];
			vc_b[0] = 1.0/3.0; vc_b[1] = 1.0/3.0; vc_b[2] = 1.0/3.0; vc_b[3] = 27.0;
			const double tmp_val1 = vc_b[3]*vc_b[3]*alpha*area/180.0*( 
				dldx[0][0]*dldx[0][0]+dldx[0][1]*dldx[0][1]+
				dldx[1][0]*dldx[1][0]+dldx[1][1]*dldx[1][1]+
				dldx[2][0]*dldx[2][0]+dldx[2][1]*dldx[2][1] );
            for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
            for(unsigned int jno_c=0;jno_c<nno_c;jno_c++){
				eCmat_cc[ino_c][jno_c] 
					= alpha*area*(dldx[ino_c][0]*dldx[jno_c][0]+dldx[ino_c][1]*dldx[jno_c][1])
					+vc_b[ino_c]*vc_b[jno_c]*tmp_val1;
			}
			}
			for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
				const double tmp1 = -1.0*vc_b[ino_c]*tmp_val1;
				eCmat_cb[ino_c] = tmp1;
				eCmat_bc[ino_c] = tmp1;
			}
			eCmat_bb = tmp_val1;
			Set_RhoTri_CB_Scalar(eMmat_cc,eMmat_cb,eMmat_bc,eMmat_bb,  area, dldx,vc_b, rho);
		}
		// 要素外力ベクトルを求める
        for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
			eqf_out_c[ino_c] = source*area*11.0/60.0;
		}
		eqf_out_b = source*area*27.0/60.0;

		////////////////////////////////////////////////////////////////

		// 要素内力ベクトルを求める
		for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
			eqf_in_c[ino_c] = 0.0;
			for(unsigned int jno_c=0;jno_c<nno_c;jno_c++){
				eqf_in_c[ino_c] += eCmat_cc[ino_c][jno_c]*(val_c[jno_c]+dt*vval_c[jno_c])
					 + eMmat_cc[ino_c][jno_c]*vval_c[jno_c];
			}
			eqf_in_c[ino_c] += eCmat_cb[ino_c]*(val_b+dt*vval_b) + eMmat_cb[ino_c]*vval_b;
		}
		eqf_in_b = 0.0;
		for(unsigned int jno_c=0;jno_c<nno_c;jno_c++){
			eqf_in_b += eCmat_bc[jno_c]*(val_c[jno_c]+dt*vval_c[jno_c]) + eMmat_bc[jno_c]*vval_c[jno_c];
		}
		eqf_in_b += eCmat_bb*(val_b+dt*vval_b) + eMmat_bb*vval_b;

		{	// 要素係数行列を求める
			double dtmp1 = gamma*dt;
			for(unsigned int i=0;i<nno_c;i++){
				for(unsigned int j=0;j<nno_c;j++){
					emat_cc[i][j] = eMmat_cc[i][j]+dtmp1*eCmat_cc[i][j];
				}
				emat_cb[i] = eMmat_cb[i]+dtmp1*eCmat_cb[i];
				emat_bc[i] = eMmat_bc[i]+dtmp1*eCmat_bc[i];
			}
			emat_bb = eMmat_bb+dtmp1*eCmat_bb;
		}
		////////////////////////////////////////////////////////////////

		// 要素残差ベクトルを求める
        for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
			eres_c[ino_c] = eqf_out_c[ino_c] - eqf_in_c[ino_c];
		}
		eres_b = eqf_out_b - eqf_in_b;
		// 要素剛性行列のマージ
		mat_cc.Mearge(nno_c,no_c,nno_c,no_c,	1,&emat_cc[0][0]);
		mat_cb.Mearge(nno_c,no_c,nno_b,&no_b,	1,&emat_cb[0]   );
		mat_bc.Mearge(nno_b,&no_b,nno_c,no_c,	1,&emat_bc[0]   );
		mat_bb.Mearge(nno_b,&no_b,nno_b,&no_b,	1,&emat_bb      );
		// 要素残差ベクトルのマージ
		for(unsigned int inoes=0;inoes<nno_c;inoes++){
			res_c.AddValue( no_c[inoes],0,eres_c[inoes]);
		}
		res_b.AddValue( no_b,0,eres_b );
	}
	return true;
}
static bool AddLinSys_AdvectionDiffusion_Static_P1P1(
		double myu, double source, 
		CLinearSystem_Field& ls, 
		const unsigned int id_field_val, const unsigned int id_field_velo, const CFieldWorld& world, 
		unsigned int id_ea )
{
//	std::cout << "Advection Diffusion Static 2D Triangle 3-point 1st order" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& val_field = world.GetField(id_field_val);

	if( !world.IsIdField(id_field_velo) ) return false;
	const CField& field_velo = world.GetField(id_field_velo);

	// 角節点の節点配列ID
	unsigned int id_na_c_co = val_field.GetNodeSegInNodeAry(CORNER).id_na_co;
	unsigned int id_ns_c_co = val_field.GetNodeSegInNodeAry(CORNER).id_ns_co;
	unsigned int id_na_c_val = val_field.GetNodeSegInNodeAry(CORNER).id_na_va;
	unsigned int id_ns_c_val = val_field.GetNodeSegInNodeAry(CORNER).id_ns_va;

	unsigned int id_na_c_velo = field_velo.GetNodeSegInNodeAry(CORNER).id_na_va;
	unsigned int id_ns_c_velo = field_velo.GetNodeSegInNodeAry(CORNER).id_ns_ve;
	assert( id_na_c_co != 0 && id_ns_c_co != 0 );
	assert( id_na_c_val != 0 && id_ns_c_val != 0 );
	assert( id_na_c_velo != 0 );
	assert( id_ns_c_velo != 0 );

	const unsigned int nno = 3;
	const unsigned int ndim = 2;

	const CElemAry::CElemSeg& es_c_val = field_velo.GetElemSeg(id_ea,CORNER,true,world);

	unsigned int no_c[nno];	// 要素節点の全体節点番号

	double value_c[nno];		// 要素節点の値
	double coord_c[nno][ndim];	// 要素節点の座標
	double velo_c[nno][ndim];
	
	double emat[nno][nno];	// 要素剛性行列
	double eres_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_val,CORNER,world);
	CVector_Blk&    res_c  = ls.GetResidual(id_field_val,CORNER,world);

	const CNodeAry& na_c_val = world.GetNA(id_na_c_val);
	const CNodeAry::CNodeSeg& ns_c_val = na_c_val.GetSeg(id_ns_c_val);
	const CNodeAry& na_c_velo = world.GetNA(id_na_c_velo);
	const CNodeAry::CNodeSeg& ns_c_velo = na_c_velo.GetSeg(id_ns_c_velo);
	const CNodeAry& na_c_co = world.GetNA(id_na_c_co);
	const CNodeAry::CNodeSeg& ns_c_co = na_c_co.GetSeg(id_ns_c_co);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c_val.GetNodes(ielem,no_c);
		// 節点の値を取って来る
		for(unsigned int inoes=0;inoes<nno;inoes++){
			ns_c_co.GetValue(no_c[inoes],coord_c[inoes]);
			ns_c_val.GetValue(no_c[inoes],&value_c[inoes]);
			ns_c_velo.GetValue(no_c[inoes],velo_c[inoes]);
		}

		////////////////////////////////////////////////////////////////

		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める			
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);

		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			emat[ino][jno] = myu*area*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]);
		}
		}
		{
			const double dtmp1 = area*0.08333333333333333333333;
			for(unsigned int ino=0;ino<nno;ino++){
				const double dtmp_0 = dtmp1*(velo_c[0][0]+velo_c[1][0]+velo_c[2][0]+velo_c[ino][0]);
				const double dtmp_1 = dtmp1*(velo_c[0][1]+velo_c[1][1]+velo_c[2][1]+velo_c[ino][1]);
				for(unsigned int jno=0;jno<nno;jno++){
					emat[ino][jno] += dldx[jno][0]*dtmp_0+dldx[jno][1]*dtmp_1;
				}
			}
		}

		// Calc Stabilization Parameter
		double tau;
		{
			const double velo_ave[2] = { 
				(velo_c[0][0]+velo_c[1][0]+velo_c[2][0])/3.0, 
				(velo_c[0][1]+velo_c[1][1]+velo_c[2][1])/3.0 };
			const double norm_v = sqrt(velo_ave[0]*velo_ave[0]+velo_ave[1]*velo_ave[1]);
			const double velo_dir[2] = { velo_ave[0]/norm_v, velo_ave[1]/norm_v };
			// calc element length along the direction of velocity
			double h;
			{
				double dtmp1 = 0;
                for(unsigned int inode=0;inode<nno;inode++){
					dtmp1 += fabs(velo_dir[0]*dldx[inode][0]+velo_dir[1]*dldx[inode][1]);
				}
				h = 2.0/dtmp1;
			}
			// calc stabilization parameter
			if( myu > 1.0e-20 ){
				const double re_c = 0.5*norm_v*h/myu;	// 0.5*norm_v*h*rho/myu;
				if(  re_c < 3.0 ){ tau = h * 0.5 / norm_v * re_c / 3.0; }
				else{ tau = h * 0.5 / norm_v; }
			}
			else{ tau = h * 0.5 / norm_v; }
		}

		{
			double tmp_mat[ndim][ndim];
			for(unsigned int idim=0;idim<ndim;idim++){
			for(unsigned int jdim=0;jdim<ndim;jdim++){
				double dtmp1 = 0.0;
				for(unsigned int ino=0;ino<nno;ino++){
					for(unsigned int jno=0;jno<nno;jno++){
						dtmp1 += velo_c[ino][idim]*velo_c[jno][jdim];
					}
					dtmp1 += velo_c[ino][idim]*velo_c[ino][jdim];
				}
				tmp_mat[idim][jdim] = area*tau*dtmp1/12.0;
			}
			}
			for(unsigned int ino=0;ino<nno;ino++){
			for(unsigned int jno=0;jno<nno;jno++){
				double dtmp1 = 0.0;
				for(unsigned int idim=0;idim<ndim;idim++){
				for(unsigned int jdim=0;jdim<ndim;jdim++){
					dtmp1 += dldx[ino][idim]*dldx[jno][jdim]*tmp_mat[idim][jdim];
				}
				}
				emat[ino][jno] += dtmp1;
			}
			}
		}


		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eres_c[ino] = source*area*0.3333333333333333333;
		}

		////////////////////////////////////////////////////////////////

		// 要素節点等価内力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){			
			for(unsigned int jno=0;jno<nno;jno++){
				eres_c[ino] -= emat[ino][jno]*value_c[jno];
			}	
		}
		// 要素剛性行列にマージする
		mat_cc.Mearge(nno,no_c,nno,no_c,1,&emat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			res_c.AddValue( no_c[ino],0,eres_c[ino]);
		}
	}
	return true;
}
Esempio n. 3
0
static bool AddLinearSystem_Diffusion2D_P1(
		double rho, double alpha, double source,
		CLinearSystem_SaveDiaM_Newmark& ls, 
		unsigned int id_field_val, const CFieldWorld& world,
		const unsigned int id_ea)
{
//	std::cout << "Diffusion2D Tri P1 savemat " << gamma << " " << dt << std::endl;

	const double gamma = ls.GetGamma();
	const double dt = ls.GetDt();

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c_val = field_val.GetElemSeg(id_ea,CORNER,true, world);
	const CElemAry::CElemSeg& es_c_co  = field_val.GetElemSeg(id_ea,CORNER,false,world);

	const unsigned int nno = 3;
	const unsigned int ndim = 2;

	unsigned int no_c[nno];	// 要素節点の全体節点番号

	double coord_c[nno][ndim];	// 要素節点の座標
				
	double emat[nno][nno];
	double eCmat[nno][nno];	// 要素剛性行列
	double eMmat[nno];	// 要素剛性行列
	double eqf_out_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& mat_cc   = ls.GetMatrix(id_field_val,CORNER,world);
	CVector_Blk&    force_c  = ls.GetForce( id_field_val,CORNER,world);
	
	CMat_BlkCrs& mat_cc_bound = ls.GetMatrix_Boundary(id_field_val,CORNER,  id_field_val,CORNER,  world);
	const CNodeAry::CNodeSeg& ns_c_co   = field_val.GetNodeSeg(CORNER,false,world,VALUE);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c_co.GetNodes(ielem,no_c);
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_co.GetValue(no_c[ino],coord_c[ino]);
		}
		es_c_val.GetNodes(ielem,no_c);

		////////////////////////////////////////////////////////////////

		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);
		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eCmat[ino][jno] = alpha*area*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]);
		}
		}
		{
			const double dtmp1 = rho*area/3.0;
			for(unsigned int ino=0;ino<nno;ino++){
				eMmat[ino] = dtmp1;
			}
		}
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eqf_out_c[ino] = source*area*0.33333333333333;
		}

		////////////////////////////////////////////////////////////////

		{	// 要素係数行列を求める
			const double dtmp1 = gamma*dt;
			for(unsigned int ino=0;ino<nno;ino++){
				for(unsigned int jno=0;jno<nno;jno++){
					emat[ino][jno] = dtmp1*eCmat[ino][jno];
				}
				emat[ino][ino] += eMmat[ino];
			}
		}

		// 剛性行列にマージする
		mat_cc      .Mearge(nno,no_c,nno,no_c,  1, &emat[0][0]);
		mat_cc_bound.Mearge(nno,no_c,nno,no_c,  1,&eCmat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			force_c.AddValue( no_c[ino],0,eqf_out_c[ino]);
		}
	}
	return true;
}
Esempio n. 4
0
static bool AddLinearSystem_Diffusion3D_P1(
		double rho, double alpha, double source,
		CLinearSystem_SaveDiaM_Newmark& ls, 
		unsigned int id_field_val, const CFieldWorld& world,
		unsigned int id_ea )
{
//	std::cout << "Diffusion3D Tet savemat" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TET );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const double gamma = ls.GetGamma();
	const double dt = ls.GetDt();

	const CElemAry::CElemSeg& es_c = field_val.GetElemSeg(id_ea,CORNER,true,world);

	const unsigned int nno = 4;
	const unsigned int ndim = 3;

	unsigned int no_c[nno];	// 要素節点の全体節点番号

	double val_c[nno];		// 要素節点の値
	double vval_c[nno];		// 要素節点の値
	double coord_c[nno][ndim];	// 要素節点の座標
				
	double emat[nno][nno];
	double eCmat[nno][nno];	// 要素剛性行列
	double eMmat[nno][nno];	// 要素剛性行列
	double eqf_out_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& mat_cc  = ls.GetMatrix(id_field_val,CORNER,world);
	CVector_Blk&    force_c = ls.GetForce( id_field_val,CORNER,world);
	
	CMat_BlkCrs& mat_cc_bound = ls.GetMatrix_Boundary(id_field_val,CORNER,  id_field_val,CORNER,  world);
	CDiaMat_Blk& mat_mass     = ls.GetDiaMassMatrix(  id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true,world,VALUE);	
	const CNodeAry::CNodeSeg& ns_c_vval = field_val.GetNodeSeg(CORNER,true,world,VELOCITY);
	const CNodeAry::CNodeSeg& ns_c_co = field_val.GetNodeSeg(CORNER,false,world,VALUE);	

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c.GetNodes(ielem,no_c);
		// 節点の値を取って来る
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_co.GetValue(no_c[ino],coord_c[ino]);
			ns_c_val.GetValue(no_c[ino],&val_c[ino]);
			ns_c_vval.GetValue(no_c[ino],&vval_c[ino]);
		}

		////////////////////////////////////////////////////////////////

		// 面積を求める
		const double vol = TetVolume(coord_c[0],coord_c[1],coord_c[2],coord_c[3]);
		// 形状関数の微分を求める
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TetDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2],coord_c[3]);
		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eCmat[ino][jno] = alpha*vol*( dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]+dldx[ino][2]*dldx[jno][2]);
		}
		}
		{
			const double dtmp1 = rho*vol*0.05;
			for(unsigned int ino=0;ino<nno;ino++){
				for(unsigned int jno=0;jno<nno;jno++){
					eMmat[ino][jno] = dtmp1;
				}
				eMmat[ino][ino] += dtmp1;
			}
		}
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eqf_out_c[ino] = source*vol*0.25;
		}

		////////////////////////////////////////////////////////////////

		{	// 要素係数行列を求める
			double dtmp1 = gamma*dt;
			for(unsigned int i=0;i<nno*nno;i++){
				(&emat[0][0])[i] = (&eMmat[0][0])[i]+dtmp1*(&eCmat[0][0])[i];
			}
		}

		// 剛性行列にマージする
		mat_cc      .Mearge(nno,no_c,nno,no_c,  1, &emat[0][0]);
		mat_cc_bound.Mearge(nno,no_c,nno,no_c,  1,&eCmat[0][0]);
		for(unsigned int ino=0;ino<nno;ino++){
			mat_mass.Mearge( no_c[ino], 1, &eMmat[0][0] );
        }

		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			force_c.AddValue( no_c[ino],0,eqf_out_c[ino]);
		}
	}
	return true;
}
Esempio n. 5
0
bool AddLinSys_StVenant3D_Static_Q1
(Fem::Eqn::ILinearSystem_Eqn& ls,
 double lambda, double myu,
 double  rho, double g_x, double g_y, double g_z,
 const unsigned int id_field_disp, const CFieldWorld& world, 
 const unsigned int	id_ea)
{
//	std::cout << "StVenant3D Hex 8-point 1st order" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == HEX );

	assert( world.IsIdField(id_field_disp) );
	const CField& field_disp = world.GetField(id_field_disp);

	const CElemAry::CElemSeg& es_c = field_disp.GetElemSeg(id_ea,CORNER,true,world);

	unsigned int num_integral = 1;
	const unsigned int nInt = NIntLineGauss[num_integral];
	const double (*Gauss)[2] = LineGauss[num_integral];
	double detjac, detwei;

	const unsigned int nnoes = 8;	assert( nnoes == es_c.Length() );
	const unsigned int ndim = 3;

	unsigned int noes[nnoes];	// 要素内の節点の節点番号

	double emat[nnoes][nnoes][ndim][ndim];	// 要素剛性行列
	double eforce_ex[nnoes][ndim];		// 要素内外力ベクトル
	double eforce_in[nnoes][ndim];		// 要素内内力ベクトル
	double eres[nnoes][ndim];		// 要素内残差ベクトル

	double ecoords[nnoes][ndim];		// 要素節点座標
	double edisp[  nnoes][ndim];		// 要素節点変位

	double dndx[nnoes][ndim];		// 形状関数の空間微分
	double an[nnoes];
				
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_disp,CORNER,world);// 要素剛性行列(コーナ-コーナー)
	CVector_Blk&     res_c = ls.GetResidual(id_field_disp,CORNER,world);// 要素残差ベクトル(コーナー)

	const CNodeAry::CNodeSeg& ns_c_val = field_disp.GetNodeSeg(CORNER,true,world,VALUE);//.GetSeg(id_ns_c_val);
	const CNodeAry::CNodeSeg& ns_c_co  = field_disp.GetNodeSeg(CORNER,false,world,VALUE);//na_c_co.GetSeg(id_ns_c_co);

//	double g[ndim] = { g_x, g_y, g_z };

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素の節点番号を取ってくる
		es_c.GetNodes(ielem,noes);
		// 節点の座標、値を取ってくる
		for(unsigned int ino=0;ino<nnoes;ino++){
			ns_c_co.GetValue(noes[ino],ecoords[ino]);
			ns_c_val.GetValue(noes[ino],edisp[ino]);
		}

		////////////////////////////////

		// 要素剛性行列、残差を0で初期化
		for(unsigned int i=0;i<nnoes*nnoes*ndim*ndim;i++){ *(&emat[0][0][0][0]+i) = 0.0; }
		for(unsigned int i=0;i<           nnoes*ndim;i++){ *(&eforce_ex[0][0] +i) = 0.0; }
		for(unsigned int i=0;i<           nnoes*ndim;i++){ *(&eforce_in[0][0] +i) = 0.0; }

		double vol = 0.0;
		for(unsigned int ir1=0;ir1<nInt;ir1++){
		for(unsigned int ir2=0;ir2<nInt;ir2++){
		for(unsigned int ir3=0;ir3<nInt;ir3++){
			const double r1 = Gauss[ir1][0];
			const double r2 = Gauss[ir2][0];
			const double r3 = Gauss[ir3][0];
			ShapeFunc_Hex8(r1,r2,r3,ecoords,detjac,dndx,an);
			detwei = detjac*Gauss[ir1][1]*Gauss[ir2][1]*Gauss[ir3][1];
			vol += detwei;
			{	// 要素剛性行列,要素内力ベクトルを作る
				double dudx[ndim][ndim] = { {0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0} };
				for(unsigned int ino=0;ino<nnoes;ino++){
					for(unsigned int idim=0;idim<ndim;idim++){
					for(unsigned int jdim=0;jdim<ndim;jdim++){
						dudx[idim][jdim] += edisp[ino][idim]*dndx[ino][jdim];
					}
					}
				}	
				SetElemMatFin_StVenant3D( vol,  myu,lambda,  nnoes,dudx,dndx,  emat[0],eforce_in );
			}
			// 要素節点等価外力ベクトルを積n分毎に足し合わせる
			for(unsigned int ino=0;ino<nnoes;ino++){
				eforce_ex[ino][0] += detwei*rho*g_x;
				eforce_ex[ino][1] += detwei*rho*g_y;
				eforce_ex[ino][2] += detwei*rho*g_z;
			}
		}
		}
		}

		////////////////////////////////

		// 要素内残差ベクトルを求める
		for(unsigned int ino=0;ino<nnoes;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eres[ino][idim] = eforce_ex[ino][idim] - eforce_in[ino][idim];
		}
		}

		////////////////////////////////
		
		mat_cc.Mearge(nnoes,noes, nnoes,noes, // 全体剛性行列に要素剛性行列をマージ
			ndim*ndim, &emat[0][0][0][0] );
		for(unsigned int ino=0;ino<nnoes;ino++){	// 要素内残差をマージ
			for(unsigned int idim=0;idim<ndim;idim++){
				res_c.AddValue(noes[ino],idim,eres[ino][idim]);
			}
		}
	}

	return true;
}
Esempio n. 6
0
static bool AddLinearSystem_Diffusion2D_AxSym_P1(
		double rho, double alpha, double source,
		double gamma, double dt,
		CLinearSystem_Field& ls, 
		unsigned int id_field_val, const CFieldWorld& world,
		const unsigned int id_ea)
{
//	std::cout << "Diffusion2D Axial Symmetry Tri P1" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c_va = field_val.GetElemSeg(id_ea,CORNER,true, world);
	const CElemAry::CElemSeg& es_c_co = field_val.GetElemSeg(id_ea,CORNER,false,world);

	const unsigned int nno = 3;
	const unsigned int ndim = 2;

	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_val,CORNER,world);
	CVector_Blk&    res_c  = ls.GetResidual(id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true,world,VALUE);
	const CNodeAry::CNodeSeg& ns_c_vval = field_val.GetNodeSeg(CORNER,true,world,VELOCITY);
	const CNodeAry::CNodeSeg& ns_c_co = field_val.GetNodeSeg(CORNER,false,world,VALUE);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		unsigned int no[nno];	// 要素節点の全体節点番号
		es_c_co.GetNodes(ielem,no);
		// 座標を取り出す
		double coord[nno][ndim];	// 要素節点の座標
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_co.GetValue(no[ino],coord[ino]);
		}
		es_c_va.GetNodes(ielem,no);
		// 節点の値を取って来る
		double val_c[nno];		// 要素節点の値
		double vval_c[nno];		// 要素節点の値
		for(unsigned int inoes=0;inoes<nno;inoes++){
			ns_c_val.GetValue(no[inoes],&val_c[inoes]);
			ns_c_vval.GetValue(no[inoes],&vval_c[inoes]);
		}

		const double rad[3] = {
			fabs( coord[0][0] ),
			fabs( coord[1][0] ),
			fabs( coord[2][0] )
		};
		const double ave_rad = (rad[0]+rad[1]+rad[2])*0.33333333333333333333;

		////////////////////////////////////////////////////////////////

		// 面積を求める
		const double area = TriArea(coord[0],coord[1],coord[2]);
		// 形状関数の微分を求める
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TriDlDx(dldx,const_term,coord[0],coord[1],coord[2]);
		// 要素剛性行列を作る
		double eCmat[nno][nno];	// 要素剛性行列
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eCmat[ino][jno] = alpha*area*ave_rad*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]);
		}
		}
		double eMmat[nno][nno];	// 要素剛性行列
		{
			const double dtmp1 = rho*area/60.0;
			eMmat[0][0] = dtmp1*(6*rad[0] + 2*rad[1] + 2*rad[2]);
			eMmat[1][1] = dtmp1*(2*rad[0] + 6*rad[1] + 2*rad[2]);
			eMmat[2][2] = dtmp1*(2*rad[0] + 2*rad[1] + 6*rad[2]);
			
			eMmat[0][1] = dtmp1*(2*rad[0] + 2*rad[1] + 1*rad[2]);
			eMmat[1][0] = eMmat[0][1];
			eMmat[0][2] = dtmp1*(2*rad[0] + 1*rad[1] + 2*rad[2]);
			eMmat[2][0] = eMmat[0][2];
			eMmat[1][2] = dtmp1*(1*rad[0] + 2*rad[1] + 2*rad[2]);
			eMmat[2][1] = eMmat[1][2];
		}
		double eres_c[nno];	// 残差ベクトル
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eres_c[ino] = source*area*0.333333333333333333;
		}

		////////////////////////////////////////////////////////////////

		double emat[nno][nno];
		{	// 要素係数行列を求める
			double dtmp1 = gamma*dt;
			for(unsigned int i=0;i<nno*nno;i++){ 
				(&emat[0][0])[i] = (&eMmat[0][0])[i]+dtmp1*(&eCmat[0][0])[i]; 
			}
		}
		// 要素節点等価内力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eres_c[ino]	-= eCmat[ino][jno]*(val_c[jno]+dt*vval_c[jno])
				         + eMmat[ino][jno]*vval_c[jno];
		}
		}
		// 要素剛性行列にマージする
		mat_cc.Mearge(nno,no,nno,no,1,&emat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			res_c.AddValue( no[ino],0,eres_c[ino]);
		}
	}
	return true;
}
Esempio n. 7
0
bool AddLinSys_StVenant2D_NonStatic_BackwardEular_P1
(double dt,
 Fem::Eqn::ILinearSystem_Eqn& ls,
 double lambda, double myu,
 double rho, double g_x, double g_y,
 const unsigned int id_field_disp, const CFieldWorld& world, 
 const MatVec::CVector_Blk& velo_pre,
 bool is_initial,
 const unsigned int id_ea )
{
	//	std::cout << "St.Venant2D Triangle 3-point 1st order" << std::endl;
	
	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );
	
	const CField& field_disp = world.GetField(id_field_disp);
	
	const CElemAry::CElemSeg& es_co = field_disp.GetElemSeg(id_ea,CORNER,false,world);
	const CElemAry::CElemSeg& es_va = field_disp.GetElemSeg(id_ea,CORNER,true,world);
	
	const unsigned int nno = 3;
	const unsigned int ndim = 2;
	
	unsigned int no[nno];	// elment node nuber 2 grobal node number
	
	double eKmat[nno][nno][ndim][ndim];	// element stiffness matrix
	double eMmat[nno][nno][ndim][ndim];	// element mass matrix		
	double eforce_in[nno][ndim];		// element residual vector		
	double eforce_ex[nno][ndim];		// element external force vector
	
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(id_field_disp,CORNER,world);	// matrix
	CVector_Blk&     res_c = ls.GetResidual(id_field_disp,CORNER,world);// residual vector
	
	const CNodeAry::CNodeSeg& ns_c_val  = field_disp.GetNodeSeg(CORNER,true,world,VALUE);
	const CNodeAry::CNodeSeg& ns_c_velo = field_disp.GetNodeSeg(CORNER,true,world,VELOCITY);
	const CNodeAry::CNodeSeg& ns_c_co   = field_disp.GetNodeSeg(CORNER,false,world);
	assert( ns_c_val.Length() == ndim );
	assert( ns_c_co.Length()  == ndim );
	
	double g[2] = { g_x, g_y };
	
	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		es_co.GetNodes(ielem,no);	// get global node number of coordinate
		double ecoords[nno][ndim];	// element node coordinate
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_co.GetValue(  no[ino], ecoords[ino]);
		}
		
		es_va.GetNodes(ielem,no);	// get global node nubmer of value
		double edisp[nno][ndim];	// displacement 
		double evelo[nno][ndim];	// velocity
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_val.GetValue( no[ino], edisp[ino]);
			ns_c_velo.GetValue(no[ino], evelo[ino]);
		}
		
		////////////////////////////////
		
		// set 0 to elemnet stiffness matrix, element residual
		for(unsigned int i=0;i<nno*nno*ndim*ndim;i++){ *(&eKmat[0][0][0][0]+i) = 0.0; }
		for(unsigned int i=0;i<nno*nno*ndim*ndim;i++){ *(&eMmat[0][0][0][0]+i) = 0.0; }
		for(unsigned int i=0;i<         nno*ndim;i++){ *(&eforce_ex[0][0]  +i) = 0.0; }
		for(unsigned int i=0;i<         nno*ndim;i++){ *(&eforce_in[0][0]  +i) = 0.0; }
		
		const double area = TriArea(ecoords[0],ecoords[1],ecoords[2]);
		
		double dldx[nno][ndim];		// spacial derivative of shape function
		double zero_order_term[nno];	// constant term of shape function
		TriDlDx(dldx, zero_order_term,   ecoords[0], ecoords[1], ecoords[2]);
		
		{	// calc stiffness matrix
            double dudx[ndim][ndim] = { { 0.0, 0.0}, {0.0, 0.0} };
			for(unsigned int ino=0;ino<nno;ino++){
				for(unsigned int idim=0;idim<ndim;idim++){
					for(unsigned int jdim=0;jdim<ndim;jdim++){
						dudx[idim][jdim] += edisp[ino][idim]*dldx[ino][jdim];
					}
				}
			}
			AddElemMatFin_StVenant2D( area, myu,lambda, nno,dudx,dldx,  eKmat[0],eforce_in );
		}
		{	// calc mass matrix
			const double tmp1 = rho*area/12.0;
			for(unsigned int ino=0;ino<nno;ino++){
				for(unsigned int jno=0;jno<nno;jno++){
					for(unsigned int idim=0;idim<ndim;idim++){
						eMmat[ino][jno][idim][idim] += tmp1;
					}
				}
				for(unsigned int idim=0;idim<ndim;idim++){
					eMmat[ino][ino][idim][idim] += tmp1;
				}
			}
		}
		// call external force
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eforce_ex[ino][idim] += area*rho*g[idim]*0.33333333333333333333;
		}
		}
		
		////////////////////////////////
		
		double emat[nno][nno][ndim][ndim];	// element coeff matrix	
		double eres[nno][ndim];		// element residual vector		
		for(unsigned int i=0;i<nno*nno*ndim*ndim;i++){
			(&emat[0][0][0][0])[i] = (&eMmat[0][0][0][0])[i] + dt*dt*(&eKmat[0][0][0][0])[i];
		}
		// get element residual vector
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eres[ino][idim] = (eforce_ex[ino][idim] - eforce_in[ino][idim])*dt;
		}
		}
		if( is_initial ){
			for(unsigned int ino=0;ino<nno;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
				for(unsigned int jno=0;jno<nno;jno++){
				for(unsigned int jdim=0;jdim<ndim;jdim++){
					eres[ino][idim] -= eKmat[ino][jno][idim][jdim]*evelo[jno][jdim]*dt*dt;
				}
				}
			}
			}
		}
		else{
			double velo0[nno][ndim];
			for(unsigned int ino=0;ino<nno;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
				velo0[ino][idim] = velo_pre.GetValue(no[ino],idim);
			}
			}
			for(unsigned int ino=0;ino<nno;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
				for(unsigned int jno=0;jno<nno;jno++){
				for(unsigned int jdim=0;jdim<ndim;jdim++){
					eres[ino][idim] -= eMmat[ino][jno][idim][jdim]*(evelo[jno][jdim]-velo0[jno][jdim]);
				}
				}
			}
			}
		}
		
		////////////////////////////////
		
		mat_cc.Mearge(nno,no, nno,no, ndim*ndim,&emat[0][0][0][0] );	// marge element stiffness
		for(unsigned int ino=0;ino<nno;ino++){	// marge element residual	
			for(unsigned int idim=0;idim<ndim;idim++){
				res_c.AddValue(no[ino],idim,eres[ino][idim]);
			}
		}
	}
	return true;
}
Esempio n. 8
0
static bool AddLinearSystem_Poisson3D_Q1(
		double alpha, double source, 
        Fem::Ls::CLinearSystem_Field& ls, 
		const unsigned int id_field_val, const CFieldWorld& world,
		const unsigned int id_ea)
{
//	std::cout << "Poisson3D Hex" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == HEX );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c_co = field_val.GetElemSeg(id_ea,CORNER,false,world);
	const CElemAry::CElemSeg& es_c_va = field_val.GetElemSeg(id_ea,CORNER,true, world);

	unsigned int num_integral = 1;
	const unsigned int nInt = NIntLineGauss[num_integral];
	const double (*Gauss)[2] = LineGauss[num_integral];

	const unsigned int nno = 8;
	const unsigned int ndim = 3;

	unsigned int no_c_co[nno];	// 要素節点の全体節点番号
	unsigned int no_c_va[nno];	// 要素節点の全体節点番号

	double value_c[nno];		// 要素節点の値
	double coord_c[nno][ndim];	// 要素節点の座標
				
	double dndx[nno][ndim];	// 形状関数のxy微分
	double an_c[nno];

	double emat[nno][nno];	// 要素剛性行列
	double eres_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_val,CORNER,world);
	CVector_Blk&    res_c  = ls.GetResidual(id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true, world);
	const CNodeAry::CNodeSeg& ns_c_co  = field_val.GetNodeSeg(CORNER,false,world);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++){
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c_co.GetNodes(ielem,no_c_co);
		for(unsigned int ino=0;ino<nno;ino++){ 
			ns_c_co.GetValue(no_c_co[ino],coord_c[ino]);
		}
		es_c_va.GetNodes(ielem,no_c_va);
		for(unsigned int ino=0;ino<nno;ino++){ 
			ns_c_val.GetValue(no_c_va[ino],&value_c[ino]);
		}
		
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			emat[ino][jno] = 0.0;
		}
		}
		for(unsigned int ino=0;ino<nno;ino++){
			eres_c[ino] = 0.0;
		}
		double vol = 0.0;
		for(unsigned int ir1=0;ir1<nInt;ir1++){
		for(unsigned int ir2=0;ir2<nInt;ir2++){
		for(unsigned int ir3=0;ir3<nInt;ir3++){
			const double r1 = Gauss[ir1][0];
			const double r2 = Gauss[ir2][0];
			const double r3 = Gauss[ir3][0];
			double detjac;
			ShapeFunc_Hex8(r1,r2,r3,coord_c,detjac,dndx,an_c);
			const double detwei = detjac*Gauss[ir1][1]*Gauss[ir2][1]*Gauss[ir3][1];
			vol += detwei;
			for(unsigned int ino=0;ino<nno;ino++){
			for(unsigned int jno=0;jno<nno;jno++){
				emat[ino][jno] += alpha*detwei*(dndx[ino][0]*dndx[jno][0]+dndx[ino][1]*dndx[jno][1]+dndx[ino][2]*dndx[jno][2]);
			}
			}
			// 要素節点等価外力ベクトルを積n分毎に足し合わせる
			for(unsigned int ino=0;ino<nno;ino++){
				eres_c[ino] += detwei*source*an_c[ino];
			}
		}
		}
		}

		// 要素節点等価内力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eres_c[ino] -= emat[ino][jno]*value_c[jno];
		}	
		}
		// 要素剛性行列にマージする
		mat_cc.Mearge(nno,no_c_va,nno,no_c_va,1,&emat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			res_c.AddValue( no_c_va[ino],0,eres_c[ino]);
		}
	}
	return true;
}
Esempio n. 9
0
bool AddLinSys_StVenant3D_NonStatic_NewmarkBeta_P1
(double gamma, double beta, double dt,
 Fem::Eqn::ILinearSystem_Eqn& ls,
 double lambda, double myu,
 double rho, double g_x, double g_y, double g_z,
 const unsigned int id_field_disp, const CFieldWorld& world, 
 bool is_initial,
 const unsigned int id_ea)
{
//	std::cout << "St.Venant3D Tet1st" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TET );

	const CField& field_disp = world.GetField(id_field_disp);

	const CElemAry::CElemSeg& es_c = field_disp.GetElemSeg(id_ea,CORNER,true,world);

	const unsigned int nnoes = 4;
	const unsigned int ndim = 3;

	double emat[nnoes][nnoes][ndim][ndim];	// coefficient element matrix
	double eMmat[nnoes][nnoes][ndim][ndim];	// mass element matrix
	double eKmat[nnoes][nnoes][ndim][ndim];	// stiffness element matrix

	double eforce_in[nnoes][ndim];		// 要素内内力ベクトル
	double eres[nnoes][ndim];		// 要素内残差ベクトル

	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_disp,CORNER,world);// 要素剛性行列(コーナ-コーナー)
	CVector_Blk&     res_c = ls.GetResidual(id_field_disp,CORNER,world);// 要素残差ベクトル(コーナー)

	const CNodeAry::CNodeSeg& ns_c_val  = field_disp.GetNodeSeg(CORNER,true,world,VALUE);
	const CNodeAry::CNodeSeg& ns_c_velo = field_disp.GetNodeSeg(CORNER,true,world,VELOCITY);
	const CNodeAry::CNodeSeg& ns_c_acc  = field_disp.GetNodeSeg(CORNER,true,world,ACCELERATION);
	const CNodeAry::CNodeSeg& ns_c_co  = field_disp.GetNodeSeg(CORNER,false,world);
	assert( ns_c_val.Length() == ndim );
	assert( ns_c_co.Length()  == ndim );

	const double g[ndim] = { g_x, g_y, g_z };

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
    {
	    unsigned int noes[nnoes];
		es_c.GetNodes(ielem,noes);
	    double ecoords[nnoes][ndim];		// coordinate 
	    double edisp[  nnoes][ndim];		// displacement 
	    double evelo[  nnoes][ndim];		// velocity
	    double eacc[  nnoes][ndim];			// acceleration
		for(unsigned int ino=0;ino<nnoes;ino++){
			ns_c_co.GetValue(  noes[ino], ecoords[ino]);
			ns_c_val.GetValue( noes[ino], edisp[ino]);
			ns_c_velo.GetValue(noes[ino], evelo[ino]);
			ns_c_acc.GetValue( noes[ino], eacc[ ino]);
		}

		////////////////////////////////

		const double vol = TetVolume(ecoords[0],ecoords[1],ecoords[2],ecoords[3]);

	    double dldx[nnoes][ndim];		// derivative of shape function
	    double zero_order_term[nnoes];	// constant term of shape function
		TetDlDx(dldx, zero_order_term,  ecoords[0],ecoords[1],ecoords[2],ecoords[3]);
		
		{	// calc stiffness matrix
			double dudx[ndim][ndim] = { {0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0} };
			for(unsigned int ino=0;ino<nnoes;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
			for(unsigned int jdim=0;jdim<ndim;jdim++){
				dudx[idim][jdim] += edisp[ino][idim]*dldx[ino][jdim];
			}
			}
			}
			SetElemMatFin_StVenant3D( vol, myu,lambda, nnoes,dudx,dldx,  eKmat[0],eforce_in );
		}

		{	// calc mass matrix
		    for(unsigned int i=0;i<nnoes*nnoes*ndim*ndim;i++){ *(&eMmat[0][0][0][0]+i) = 0.0; }
			const double tmp1 = rho*vol*0.05;
			for(unsigned int ino=0;ino<nnoes;ino++){
			for(unsigned int jno=0;jno<nnoes;jno++){
				eMmat[ino][jno][0][0] += tmp1;
				eMmat[ino][jno][1][1] += tmp1;
				eMmat[ino][jno][2][2] += tmp1;
            }
            }
			for(unsigned int ino=0;ino<nnoes;ino++){
				eMmat[ino][ino][0][0] += tmp1;
				eMmat[ino][ino][1][1] += tmp1;
				eMmat[ino][ino][2][2] += tmp1;
			}
		}

		////////////////////////////////

		for(unsigned int i=0;i<nnoes*nnoes*ndim*ndim;i++){
			(&emat[0][0][0][0])[i] = (&eMmat[0][0][0][0])[i] + beta*dt*dt*(&eKmat[0][0][0][0])[i];
		}
		for(unsigned int ino=0;ino<nnoes;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eres[ino][idim] = vol*rho*g[idim]*0.25 - eforce_in[ino][idim];
			for(unsigned int jno=0;jno<nnoes;jno++){
			for(unsigned int jdim=0;jdim<ndim;jdim++){
				eres[ino][idim] -= eMmat[ino][jno][idim][jdim]*eacc[jno][jdim];
			}
			}
		}
		}
		if( is_initial ){
			for(unsigned int ino=0;ino<nnoes;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
				for(unsigned int jno=0;jno<nnoes;jno++){
				for(unsigned int jdim=0;jdim<ndim;jdim++){
					eres[ino][idim] -= dt*eKmat[ino][jno][idim][jdim]*evelo[jno][jdim]
						+ 0.5*dt*dt*eKmat[ino][jno][idim][jdim]*eacc[jno][jdim];
				}
				}
			}
			}
		}

		////////////////////////////////
		
		mat_cc.Mearge(nnoes,noes, nnoes,noes, ndim*ndim,&emat[0][0][0][0] );
		for(unsigned int ino=0;ino<nnoes;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			res_c.AddValue(noes[ino],idim,eres[ino][idim]);
		}
		}
	}
	return true;
}
Esempio n. 10
0
bool AddLinSys_StVenant2D_Static_P1(
        Fem::Eqn::ILinearSystem_Eqn& ls,
		double lambda, double myu,
		double  rho, double g_x, double g_y,
		const unsigned int id_field_disp, const CFieldWorld& world, 
		const unsigned int id_ea)
{
	
//	std::cout << "St.Venant2D Static Tri3point" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );
	const CField& field_disp = world.GetField(id_field_disp);

	const CElemAry::CElemSeg& es_co = field_disp.GetElemSeg(id_ea,CORNER,false,world);
	const CElemAry::CElemSeg& es_va = field_disp.GetElemSeg(id_ea,CORNER,true, world);

	const unsigned int nnoes = 3;
	const unsigned int ndim = 2;

	unsigned int noes[nnoes];	// 要素内の節点の節点番号

	double emat[nnoes][nnoes][ndim][ndim];	// 要素剛性行列
	double eforce_ex[nnoes][ndim];		// 要素内外力ベクトル
	double eforce_in[nnoes][ndim];		// 要素内内力ベクトル
	double eres[nnoes][ndim];		// 要素内残差ベクトル

	double ecoords[nnoes][ndim];		// 要素節点座標
	double edisp[  nnoes][ndim];		// 要素節点変位

	double dldx[nnoes][ndim];		// 形状関数の空間微分
	double zero_order_term[nnoes];	// 形状関数の定数項
				
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_disp,CORNER,world);	// 要素剛性行列(コーナ-コーナー)
	CVector_Blk&     res_c = ls.GetResidual(id_field_disp,CORNER,world);	// 要素残差ベクトル(コーナー)

	const CNodeAry::CNodeSeg& ns_c_val = field_disp.GetNodeSeg(CORNER,true,world,VALUE);
	const CNodeAry::CNodeSeg& ns_c_co  = field_disp.GetNodeSeg(CORNER,false,world);
/*
	unsigned int num_integral = 0;
	const unsigned int nInt = NIntTriGauss[num_integral];
	const double (*Gauss)[3] = TriGauss[num_integral];
*/
	double g[2] = { g_x, g_y };

	for(unsigned int ielem=0;ielem<ea.Size();ielem++){
		// 要素の節点番号を取ってくる
		es_co.GetNodes(ielem,noes);
		// 節点の座標、値を取ってくる
		for(unsigned int ino=0;ino<nnoes;ino++){
			ns_c_co.GetValue(noes[ino],ecoords[ino]);
		}
		// 要素の節点番号を取ってくる
		es_va.GetNodes(ielem,noes);
		// 節点の座標、値を取ってくる
		for(unsigned int ino=0;ino<nnoes;ino++){
			ns_c_val.GetValue(noes[ino],edisp[ino]);
		}

		////////////////////////////////

		// 要素剛性行列、残差を0で初期化
		for(unsigned int i=0;i<nnoes*nnoes*ndim*ndim;i++){ *(&emat[0][0][0][0]+i) = 0.0; }
		for(unsigned int i=0;i<           nnoes*ndim;i++){ *(&eforce_ex[0][0] +i) = 0.0; }
		for(unsigned int i=0;i<           nnoes*ndim;i++){ *(&eforce_in[0][0] +i) = 0.0; }

		// 面積を求める
		const double area = TriArea(ecoords[0],ecoords[1],ecoords[2]);

		// 形状関数のxy微分を求める
		TriDlDx(dldx, zero_order_term,   ecoords[0], ecoords[1], ecoords[2]);

        double dudx[ndim][ndim] = { { 0.0, 0.0}, {0.0, 0.0} };
		for(unsigned int ino=0;ino<nnoes;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
			for(unsigned int jdim=0;jdim<ndim;jdim++){
				dudx[idim][jdim] += edisp[ino][idim]*dldx[ino][jdim];
			}
			}
		}

		AddElemMatFin_StVenant2D( area, myu,lambda, nnoes,dudx,dldx,  emat[0],eforce_in );

		// 外力ベクトルを求める
		for(unsigned int ino=0;ino<nnoes;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eforce_ex[ino][idim] += area*rho*g[idim]/nnoes;
		}
		}

		////////////////////////////////

		// 要素内残差ベクトルを求める
		for(unsigned int ino=0;ino<nnoes;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eres[ino][idim] = eforce_ex[ino][idim] - eforce_in[ino][idim];
		}
		}

		////////////////////////////////
		
		mat_cc.Mearge(nnoes,noes, nnoes,noes, // 全体剛性行列に要素剛性行列をマージ
			ndim*ndim,&emat[0][0][0][0] );
		for(unsigned int ino=0;ino<nnoes;ino++){	// 要素内残差をマージ
		for(unsigned int idim=0;idim<ndim;idim++){
			res_c.AddValue(noes[ino],idim,eres[ino][idim]);
		}
		}
	}

	return true;
}
Esempio n. 11
0
static bool AddLinearSystem_Wave2D_P1(
		double rho, double alpha, double source, 
		CLinearSystem_Eigen& ls, 
		const unsigned int id_field_val, const CFieldWorld& world,
		const unsigned int id_ea )
{
//	std::cout << "Wave2D TriP1" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c_co = field_val.GetElemSeg(id_ea,CORNER,false,world);

	const unsigned int nno = 3;
	const unsigned int ndim = 2;

	unsigned int no_c[nno];	// 要素節点の全体節点番号
	double coord_c[nno][ndim];	// 要素節点の座標
				
	double eKmat[nno][nno];	// 要素剛性行列
	double eMmat[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& Kmat_cc = ls.GetMatrix(       id_field_val,CORNER,world);
	CDiaMat_Blk&    Mmat_cc = ls.GetDiaMassMatrix(id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_co  = field_val.GetNodeSeg(CORNER,false,world);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c_co.GetNodes(ielem,no_c);
		for(unsigned int inoes=0;inoes<nno;inoes++){
			ns_c_co.GetValue(no_c[inoes],coord_c[inoes]);
		}
		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);
		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eKmat[ino][jno] = alpha*area*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]);
		}
		}
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eMmat[ino] = rho*area*0.33333333333333333;
		}
		// 要素剛性行列にマージする
		Kmat_cc.Mearge(nno,no_c,nno,no_c,1,&eKmat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			Mmat_cc.Mearge(no_c[ino],1,&eMmat[ino]);
		}
	}
	return true;
}
Esempio n. 12
0
static bool AddLinearSystem_Poisson2D_P1b(
		double alpha, double source, 
        Fem::Ls::CLinearSystem_Save& ls, 
		const unsigned int id_field_val, const CFieldWorld& world,
		const unsigned int id_ea)
{
	std::cout << "Poisson2D Triangle 3-point 1st order" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c = field_val.GetElemSeg(id_ea,CORNER,true,world);
	const CElemAry::CElemSeg& es_b = field_val.GetElemSeg(id_ea,BUBBLE,true,world);

	const unsigned int nno_c = 3;
	const unsigned int nno_b = 1;
	const unsigned int ndim = 2;

	unsigned int no_c[nno_c];	// 要素節点の全体節点番号
	unsigned int no_b;	// 要素節点の全体節点番号

	double value_c[nno_c], value_b;	// 要素節点の値
	double coord_c[nno_c][ndim];	// 要素節点の座標
				
	double dldx[nno_c][ndim];	// 形状関数のxy微分
	double const_term[nno_c];	// 形状関数の定数項

	double emat_cc[nno_c][nno_c], emat_bb, emat_cb[nno_c], emat_bc[nno_c];	// 要素剛性行列
	double eqf_out_c[nno_c];	// 要素節点等価内力、外力、残差ベクトル
	double eqf_out_b;	// 要素節点等価内力、外力、残差ベクトル

	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(id_field_val,CORNER,world);
	CMatDia_BlkCrs& mat_bb = ls.GetMatrix(id_field_val,BUBBLE,world);
	CMat_BlkCrs& mat_cb = ls.GetMatrix(id_field_val,CORNER, id_field_val,BUBBLE, world);
	CMat_BlkCrs& mat_bc = ls.GetMatrix(id_field_val,BUBBLE, id_field_val,CORNER, world);
	CMat_BlkCrs& mat_cc_bound = ls.GetMatrix_Boundary(id_field_val,CORNER, id_field_val,CORNER, world);
	CMat_BlkCrs& mat_bb_bound = ls.GetMatrix_Boundary(id_field_val,BUBBLE, id_field_val,BUBBLE, world);
	CMat_BlkCrs& mat_cb_bound = ls.GetMatrix_Boundary(id_field_val,CORNER, id_field_val,BUBBLE, world);
	CMat_BlkCrs& mat_bc_bound = ls.GetMatrix_Boundary(id_field_val,BUBBLE, id_field_val,CORNER, world);
	CVector_Blk& force_c = ls.GetForce(id_field_val,CORNER,world);
	CVector_Blk& force_b = ls.GetForce(id_field_val,BUBBLE,world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true, world);
	const CNodeAry::CNodeSeg& ns_b_val = field_val.GetNodeSeg(BUBBLE,true, world);
	const CNodeAry::CNodeSeg& ns_c_co  = field_val.GetNodeSeg(CORNER,false,world);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c.GetNodes(ielem,no_c);
		es_b.GetNodes(ielem,&no_b);
		// 節点の値を取ってくる
		for(unsigned int inoes=0;inoes<nno_c;inoes++){
			ns_c_co.GetValue(no_c[inoes],coord_c[inoes]);
			ns_c_val.GetValue(no_c[inoes],&value_c[inoes]);
		}
		ns_b_val.GetValue(no_b,&value_b);

		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);
		{	// 要素剛性行列を作る
			double vc_b[4];
			vc_b[0] = 1.0/3.0; vc_b[1] = 1.0/3.0; vc_b[2] = 1.0/3.0; vc_b[3] = 27.0;
			const double tmp_val1 = vc_b[3]*vc_b[3]*area/180.0*( 
				dldx[0][0]*dldx[0][0]+dldx[0][1]*dldx[0][1]+
				dldx[1][0]*dldx[1][0]+dldx[1][1]*dldx[1][1]+
				dldx[2][0]*dldx[2][0]+dldx[2][1]*dldx[2][1] );
			double tmp1;
			for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
			for(unsigned int jno_c=0;jno_c<nno_c;jno_c++){
				tmp1 = 
					area*(dldx[ino_c][0]*dldx[jno_c][0]+dldx[ino_c][1]*dldx[jno_c][1])
					+vc_b[ino_c]*vc_b[jno_c]*tmp_val1;
				emat_cc[ino_c][jno_c] = tmp1;
			}
			}
			for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
				tmp1 = -1.0*vc_b[ino_c]*tmp_val1;
				emat_cb[ino_c] = tmp1;
				emat_bc[ino_c] = tmp1;
			}
			emat_bb = tmp_val1;
		}
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino_c=0;ino_c<nno_c;ino_c++){
			eqf_out_c[ino_c] = source*area*11.0/60.0;
		}
		eqf_out_b = source*area*27.0/60.0;
		// 要素剛性行列の全体剛性行列へのマージ
		mat_cc.Mearge(nno_c,no_c,nno_c,no_c,	1,&emat_cc[0][0]);
		mat_cb.Mearge(nno_c,no_c,nno_b,&no_b,	1,&emat_cb[0]   );
		mat_bc.Mearge(nno_b,&no_b,nno_c,no_c,	1,&emat_bc[0]   );
		mat_bb.Mearge(nno_b,&no_b,nno_b,&no_b,	1,&emat_bb      );
		////////////////
		mat_cc_bound.Mearge(nno_c, no_c,nno_c, no_c,	1,&emat_cc[0][0]);
		mat_cb_bound.Mearge(nno_c, no_c,nno_b,&no_b,	1,&emat_cb[0]   );
		mat_bc_bound.Mearge(nno_b,&no_b,nno_c, no_c,	1,&emat_bc[0]   );
		mat_bb_bound.Mearge(nno_b,&no_b,nno_b,&no_b,	1,&emat_bb      );
		// 残差ベクトルのマージ
		for(unsigned int inoes=0;inoes<nno_c;inoes++){
			force_c.AddValue( no_c[inoes],0,eqf_out_c[inoes]);
		}
		force_b.AddValue( no_b,0,eqf_out_b );
	}
	return true;
}
Esempio n. 13
0
bool AddLinearSystem_Poisson2D_P1(
		double alpha, double source, 
		CLinearSystem_Save& ls, 
		unsigned int id_field_val, const CFieldWorld& world,
		unsigned int id_ea)
{
//	std::cout << "Poisson2D Tri P1" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c_va = field_val.GetElemSeg(id_ea,CORNER,true, world);
	const CElemAry::CElemSeg& es_c_co = field_val.GetElemSeg(id_ea,CORNER,false,world);

	const unsigned int nno = 3;
	const unsigned int ndim = 2;

	unsigned int no_c[nno];	// 要素節点の全体節点番号

	double value_c[nno];		// 要素節点の値
	double coord_c[nno][ndim];	// 要素節点の座標
				
	double emat[nno][nno];	// 要素剛性行列
	double eqf_out_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs&      mat_cc  = ls.GetMatrix(id_field_val,CORNER,world);
	CVector_Blk&         force_c = ls.GetForce(id_field_val,CORNER,world);
	CMat_BlkCrs& mat_cc_boundary = ls.GetMatrix_Boundary(id_field_val,CORNER,id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true, world);//na_c_val.GetSeg(id_ns_c_val);
	const CNodeAry::CNodeSeg& ns_c_co  = field_val.GetNodeSeg(CORNER,false,world);//na_c_co.GetSeg(id_ns_c_co);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c_co.GetNodes(ielem,no_c);
		// 節点の値を取って来る
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_co.GetValue(no_c[ino],coord_c[ino]);
		}
		es_c_va.GetNodes(ielem,no_c);
		// 節点の値を取って来る
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_val.GetValue(no_c[ino],&value_c[ino]);
		}

		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);
		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			emat[ino][jno] = alpha*area*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]);
		}
		}
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eqf_out_c[ino] = source*area*0.333333333333333333;
		}
		// 要素剛性行列にマージする
		mat_cc.Mearge(         nno,no_c,nno,no_c,1,&emat[0][0]);
		mat_cc_boundary.Mearge(nno,no_c,nno,no_c,1,&emat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			force_c.AddValue( no_c[ino],0,eqf_out_c[ino]);
		}
	}
	return true;
}
Esempio n. 14
0
static bool AddLinSys_AdvectionDiffusion_NonStatic_Newmark_P1P1(
		double rho, double myu, double source, 
		CLinearSystem_SaveDiaM_Newmark& ls, 
		const unsigned int id_field_val, const unsigned int id_field_velo, const CFieldWorld& world, 
		unsigned int id_ea )
{
//	std::cout << "Poisson2D Triangle 3-point 1st order" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TRI );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& val_field = world.GetField(id_field_val);

	if( !world.IsIdField(id_field_velo) ) return false;
	const CField& field_velo = world.GetField(id_field_velo);

	const double gamma = ls.GetGamma();
	const double dt = ls.GetDt();

	const unsigned int nno = 3;
	const unsigned int ndim = 2;

	const CElemAry::CElemSeg& es_c_val = val_field.GetElemSeg(id_ea,CORNER,true,world);

	double emat[nno][nno];	// 要素剛性行列
	double eqf_out_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& mat_cc  = ls.GetMatrix(id_field_val,CORNER,world);
	CVector_Blk&    force_c = ls.GetForce( id_field_val,CORNER,world);

	CMat_BlkCrs& mat_cc_bound = ls.GetMatrix_Boundary(id_field_val,CORNER,id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_val = val_field.GetNodeSeg(CORNER,true,world,VALUE);		//na_c_val.GetSeg(id_ns_c_val);
	const CNodeAry::CNodeSeg& ns_c_vval = val_field.GetNodeSeg(CORNER,true,world,VELOCITY);	//na_c_val.GetSeg(id_ns_c_vval);
	const CNodeAry::CNodeSeg& ns_c_velo = field_velo.GetNodeSeg(CORNER,true,world,VELOCITY);//na_c_velo.GetSeg(id_ns_c_velo);
	const CNodeAry::CNodeSeg& ns_c_co = field_velo.GetNodeSeg(CORNER,false,world,VALUE);	//na_c_co.GetSeg(id_ns_c_co);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		unsigned int no_c[nno];	// 要素節点の全体節点番号
		es_c_val.GetNodes(ielem,no_c);
		// 節点の値を取って来る
		double val_c[nno], vval_c[nno];		// 要素節点の値
		double coord_c[nno][ndim];	// 要素節点の座標
		double velo_c[nno][ndim];	// advection velocity
		for(unsigned int ino=0;ino<nno;ino++){
			ns_c_val.GetValue(no_c[ino],&val_c[ino]);
			ns_c_vval.GetValue(no_c[ino],&vval_c[ino]);
			ns_c_velo.GetValue(no_c[ino],velo_c[ino]);
			ns_c_co.GetValue(no_c[ino],coord_c[ino]);
		}

		////////////////////////////////////////////////////////////////

		// 面積を求める
		const double area = TriArea(coord_c[0],coord_c[1],coord_c[2]);
		// 形状関数の微分を求める
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TriDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2]);

		double eCmat[nno][nno];
		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eCmat[ino][jno] = myu*area*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]);
		}
		}
		{
			const double dtmp1 = area/12.0;
			for(unsigned int ino=0;ino<nno;ino++){
				const double dtmp_0 = dtmp1*(velo_c[0][0]+velo_c[1][0]+velo_c[2][0]+velo_c[ino][0]);
				const double dtmp_1 = dtmp1*(velo_c[0][1]+velo_c[1][1]+velo_c[2][1]+velo_c[ino][1]);
                for(unsigned int jno=0;jno<nno;jno++){
					eCmat[ino][jno] += dldx[jno][0]*dtmp_0+dldx[jno][1]*dtmp_1;
				}
			}
		}

		// Calc Stabilization Parameter
		double tau;
		{
			const double velo_ave[2] = { 
				(velo_c[0][0]+velo_c[1][0]+velo_c[2][0])/3.0, 
				(velo_c[0][1]+velo_c[1][1]+velo_c[2][1])/3.0 };
			const double norm_v = sqrt(velo_ave[0]*velo_ave[0]+velo_ave[1]*velo_ave[1]);
			const double velo_dir[2] = { velo_ave[0]/norm_v, velo_ave[1]/norm_v };			
			double h;
			{	// calc element length along the direction of velocity
				double dtmp1 = 0;
				for(int inode=0;inode<3;inode++){
					dtmp1 += fabs(velo_dir[0]*dldx[inode][0]+velo_dir[1]*dldx[inode][1]);
				}
				h = 2.0/dtmp1;
			}
			// calc stabilization parameter
			if( norm_v*h*rho < 6.0*myu ){
				const double re_c = 0.5*norm_v*h*rho/myu;	// 0.5*norm_v*h*rho/myu;
				tau = h * 0.5 / norm_v * re_c / 3.0;
			}
			else{ tau = h * 0.5 / norm_v; }
//			tau *= 0.1;
		}

		{
			double tmp_mat[ndim][ndim];
			for(unsigned int idim=0;idim<ndim;idim++){
			for(unsigned int jdim=0;jdim<ndim;jdim++){
				double dtmp1 = 0.0;
				for(unsigned int ino=0;ino<nno;ino++){
					for(unsigned int jno=0;jno<nno;jno++){
						dtmp1 += velo_c[ino][idim]*velo_c[jno][jdim];
					}
					dtmp1 += velo_c[ino][idim]*velo_c[ino][jdim];
				}
				tmp_mat[idim][jdim] = area*tau*dtmp1/12.0;
			}
			}
			for(unsigned int ino=0;ino<nno;ino++){
			for(unsigned int jno=0;jno<nno;jno++){
				double dtmp1 = 0.0;
				for(unsigned int idim=0;idim<ndim;idim++){
				for(unsigned int jdim=0;jdim<ndim;jdim++){
					dtmp1 += dldx[ino][idim]*dldx[jno][jdim]*tmp_mat[idim][jdim];
				}
				}
				eCmat[ino][jno] += dtmp1;
			}
			}
		}

		double eMmat[nno][nno];
		{
			const double dtmp1 = rho*area*0.08333333333333333333333333;
			for(unsigned int ino=0;ino<nno;ino++){
				for(unsigned int jno=0;jno<nno;jno++){
					eMmat[ino][jno] = dtmp1;
				}
				eMmat[ino][ino] += dtmp1;
			}
		}

		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eqf_out_c[ino] = source*area*0.333333333333333333333;
		}

		////////////////////////////////////////////////////////////////

		{	// 要素係数行列を求める
			double dtmp1 = gamma*dt;
			for(unsigned int i=0;i<nno*nno;i++){
				(&emat[0][0])[i] = (&eMmat[0][0])[i]+dtmp1*(&eCmat[0][0])[i];
			}
		}
		// 要素剛性行列にマージする
		mat_cc      .Mearge(nno,no_c,nno,no_c,1, &emat[0][0]);
		mat_cc_bound.Mearge(nno,no_c,nno,no_c,1,&eCmat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int ino=0;ino<nno;ino++){
			force_c.AddValue( no_c[ino],0,eqf_out_c[ino]);
		}
	}
	return true;
}
Esempio n. 15
0
bool AddLinSys_StVenant3D_Static_P1
(Fem::Eqn::ILinearSystem_Eqn& ls,
 double lambda, double myu,
 double  rho, double g_x, double g_y, double g_z,
 const unsigned int id_field_disp, const CFieldWorld& world, 
 unsigned int id_ea)
{
//	std::cout << "StVenant3D Tet 4-point 1st order" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TET );

	const CField& field_disp = world.GetField(id_field_disp);

	const CElemAry::CElemSeg& es_c = field_disp.GetElemSeg(id_ea,CORNER,true,world);

	const unsigned int nnoes = 4;	assert( nnoes == es_c.Length() );
	const unsigned int ndim = 3;

	unsigned int noes[nnoes];	// 要素内の節点の節点番号

	double emat[nnoes][nnoes][ndim][ndim];	// 要素剛性行列
	double eforce_ex[nnoes][ndim];		// 要素内外力ベクトル
	double eforce_in[nnoes][ndim];		// 要素内内力ベクトル
	double eres[nnoes][ndim];		// 要素内残差ベクトル

	double ecoords[nnoes][ndim];		// 要素節点座標
	double edisp[  nnoes][ndim];		// 要素節点変位

	double dldx[nnoes][ndim];		// 形状関数の空間微分
	double zero_order_term[nnoes];	// 形状関数の定数項
				
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_disp,CORNER,world);// 要素剛性行列(コーナ-コーナー)
	CVector_Blk&    res_c  = ls.GetResidual(id_field_disp,CORNER,world);// 要素残差ベクトル(コーナー)

	const CNodeAry::CNodeSeg& ns_c_val = field_disp.GetNodeSeg(CORNER,true,world,VALUE);//.GetSeg(id_ns_c_val);
	const CNodeAry::CNodeSeg& ns_c_co  = field_disp.GetNodeSeg(CORNER,false,world,VALUE);//na_c_co.GetSeg(id_ns_c_co);

	double g[ndim] = { g_x, g_y, g_z };

	for(unsigned int ielem=0;ielem<ea.Size();ielem++){
		// 要素の節点番号を取ってくる
		es_c.GetNodes(ielem,noes);
		// 節点の座標、値を取ってくる
		for(unsigned int ino=0;ino<nnoes;ino++){
			ns_c_co.GetValue(noes[ino],ecoords[ino]);
			ns_c_val.GetValue(noes[ino],edisp[ino]);
		}

		////////////////////////////////

		// 要素剛性行列、残差を0で初期化
		for(unsigned int i=0;i<nnoes*nnoes*ndim*ndim;i++){ *(&emat[0][0][0][0]+i) = 0.0; }
		for(unsigned int i=0;i<           nnoes*ndim;i++){ *(&eforce_ex[0][0] +i) = 0.0; }
		for(unsigned int i=0;i<           nnoes*ndim;i++){ *(&eforce_in[0][0] +i) = 0.0; }

		// 面積を求める
		const double vol = TetVolume(ecoords[0],ecoords[1],ecoords[2],ecoords[3]);

		// 形状関数のxy微分を求める
		TetDlDx(dldx, zero_order_term,   ecoords[0],ecoords[1],ecoords[2],ecoords[3]);

		{	// 要素剛性行列,要素内力ベクトルを作る
			double dudx[ndim][ndim] = { {0.0,0.0,0.0}, {0.0,0.0,0.0}, {0.0,0.0,0.0} };
			for(unsigned int ino=0;ino<nnoes;ino++){
				for(unsigned int idim=0;idim<ndim;idim++){
				for(unsigned int jdim=0;jdim<ndim;jdim++){
					dudx[idim][jdim] += edisp[ino][idim]*dldx[ino][jdim];
				}
				}
			}	
			SetElemMatFin_StVenant3D( vol,  myu,lambda,  nnoes,dudx,dldx,  emat[0],eforce_in );
		}
		// 外力ベクトルを求める
		for(unsigned int ino=0;ino<nnoes;ino++){
			for(unsigned int idim=0;idim<ndim;idim++){
				eforce_ex[ino][idim] += vol*rho*g[idim]/nnoes;
			}
		}

		////////////////////////////////

		// 要素内残差ベクトルを求める
		for(unsigned int ino=0;ino<nnoes;ino++){
		for(unsigned int idim=0;idim<ndim;idim++){
			eres[ino][idim] = eforce_ex[ino][idim] - eforce_in[ino][idim];
		}
		}

		////////////////////////////////
		
		mat_cc.Mearge(nnoes,noes, nnoes,noes, // 全体剛性行列に要素剛性行列をマージ
			ndim*ndim, &emat[0][0][0][0] );
		for(unsigned int ino=0;ino<nnoes;ino++){	// 要素内残差をマージ
			for(unsigned int idim=0;idim<ndim;idim++){
				res_c.AddValue(noes[ino],idim,eres[ino][idim]);
			}
		}
	}
	return true;
}
// 対角にパターンを追加
bool CZLinearSystem::AddPattern_Field(const unsigned int id_field, const CFieldWorld& world)
{
	if( !world.IsIdField(id_field) ) return false;
	const CField& field = world.GetField(id_field);
	unsigned int id_field_parent;
	{
		if( field.GetIDFieldParent() == 0 ){ id_field_parent = id_field; }
		else{ id_field_parent = field.GetIDFieldParent(); }
	}

	unsigned int nlen_value;
	{	// 複素数の場合は2で割る
		const unsigned int nlen = field.GetNLenValue();
		assert( nlen % 2 == 0 );
		nlen_value = nlen / 2;
	}

	int ESType2iLS[3];
	{	// Bubbleブロックを作る
		unsigned int id_na_val = field.GetNodeSegInNodeAry(BUBBLE).id_na_va;
		if( id_na_val != 0 ){
			assert( world.IsIdNA(id_na_val) );
			const CNodeAry& na = world.GetNA(id_na_val);
			CLinSysSeg seg;
			{
				seg.id_field = id_field_parent; seg.node_config = BUBBLE;
				seg.len=nlen_value; seg.nnode=na.Size();
			}
			ESType2iLS[2] = this->AddLinSysSeg(seg);
		}
		else{ ESType2iLS[2] = -1; }
	}
	{	// Edgeブロックを作る
		unsigned int id_na_val = field.GetNodeSegInNodeAry(EDGE).id_na_va;
		if( id_na_val != 0 ){
			assert( world.IsIdNA(id_na_val) );
			const CNodeAry& na = world.GetNA(id_na_val);
			CLinSysSeg seg;
			{
				seg.id_field = id_field_parent; seg.node_config = EDGE;
				seg.len=nlen_value; seg.nnode=na.Size();
			}
			ESType2iLS[1] = this->AddLinSysSeg(seg);
		}
		else{ ESType2iLS[1] = -1; }
	}
	{	// Cornerブロックを作る
		unsigned int id_na_val = field.GetNodeSegInNodeAry(CORNER).id_na_va;
		if( id_na_val != 0 ){
			assert( world.IsIdNA(id_na_val) );
			const CNodeAry& na = world.GetNA(id_na_val);
			CLinSysSeg seg;
			{
				seg.id_field = id_field_parent; seg.node_config = CORNER;
				seg.len=nlen_value; seg.nnode=na.Size();
			}
			ESType2iLS[0] = this->AddLinSysSeg(seg);
		}
		else{ ESType2iLS[0] = -1; }
	}
	////////////////////////////////
	const std::vector<unsigned int> aIdEA = field.GetAryIdEA();
	if( aIdEA.size() == 0 ){ // 剛体モードのための行列
		unsigned int ils0 = ESType2iLS[0];
		if( m_Matrix_Dia[ils0] == 0 ){
			m_Matrix_Dia[ils0] = new CZMatDia_BlkCrs(1, nlen_value);
		}
		return true;
	}

	for(unsigned int iiea=0;iiea<aIdEA.size();iiea++)
	{
		const unsigned int id_ea = aIdEA[iiea];
		const CElemAry& ea = world.GetEA(id_ea);
		// CORNER節点について
		if( field.GetIdElemSeg(id_ea,CORNER,true,world) != 0 ){
			assert( world.IsIdEA(id_ea) );
			const unsigned int id_es_c = field.GetIdElemSeg(id_ea,CORNER,true,world);
			assert( ea.IsSegID(id_es_c) );
			const unsigned int ils0 = ESType2iLS[0];
			this->AddMat_Dia(ils0, ea, id_es_c );			// cc行列を作る
			if( field.GetIdElemSeg(id_ea,BUBBLE,true,world) != 0 ){	// CORNER-BUBBLE
				const unsigned int id_es_b = field.GetIdElemSeg(id_ea,BUBBLE,true,world);
				assert( ea.IsSegID(id_es_b) );
				const unsigned int ils1 = ESType2iLS[2];
				Com::CIndexedArray crs;
				ea.MakePattern_FEM(id_es_c,id_es_b,crs);
				assert( crs.CheckValid() );
				this->AddMat_NonDia(ils0,ils1, crs);		// cb行列を作る
				const unsigned int nnode1 = m_aSeg[ils1].nnode;
				Com::CIndexedArray crs_inv;
				crs_inv.SetTranspose(nnode1,crs);
				this->AddMat_NonDia(ils1,ils0, crs_inv);	// bc行列を作る
			}
			if( field.GetIdElemSeg(id_ea,EDGE,true,world) != 0 ){	// CONRER-EDGE
				const unsigned int id_es_e = field.GetIdElemSeg(id_ea,EDGE,true,world);
				assert( ea.IsSegID(id_es_e) );
				const unsigned int ils1 = ESType2iLS[1];
				Com::CIndexedArray crs;
				ea.MakePattern_FEM(id_es_c,id_es_e,crs);
				assert( crs.CheckValid() );
				this->AddMat_NonDia(ils0,ils1, crs);		// ce行列を作る
				const unsigned int nnode1 = m_aSeg[ils1].nnode;
				Com::CIndexedArray crs_inv;
				crs_inv.SetTranspose(nnode1,crs);
				this->AddMat_NonDia(ils1,ils0, crs_inv);	// ec行列を作る
			}
		}
		// EDGE節点について
		if( field.GetIdElemSeg(id_ea,EDGE,true,world) != 0 ){
			const unsigned int id_es_e = field.GetIdElemSeg(id_ea,EDGE,true,world);
			assert( ea.IsSegID(id_es_e) );
			const unsigned int ils0 = ESType2iLS[1];
			this->AddMat_Dia(ils0, ea, id_es_e);			// ee行列を作る
			if( field.GetIdElemSeg(id_ea,BUBBLE,true,world) != 0 ){	// EDGE-BUBBLE
				const unsigned int id_es_b = field.GetIdElemSeg(id_ea,BUBBLE,true,world);
				assert( ea.IsSegID(id_es_b) );
				const unsigned int ils1 = ESType2iLS[2];
				Com::CIndexedArray crs;
				ea.MakePattern_FEM(id_es_e,id_es_b,crs);
				assert( crs.CheckValid() );
				this->AddMat_NonDia(ils0,ils1, crs);		// eb行列を作る
				const unsigned int nnode1 = m_aSeg[ils1].nnode;
				Com::CIndexedArray crs_inv;
				crs_inv.SetTranspose(nnode1,crs);
				this->AddMat_NonDia(ils1,ils0, crs_inv);	// be行列を作る
			}
		}
		// BUBBLE節点について
		if( field.GetIdElemSeg(id_ea,BUBBLE,true,world) != 0 ){
			const unsigned int id_es_b = field.GetIdElemSeg(id_ea,BUBBLE,true,world);
			assert( ea.IsSegID(id_es_b) );
			const unsigned int ils0 = ESType2iLS[2];
			this->AddMat_Dia(ils0, ea, id_es_b);
		}
	}
	return true;
}
Esempio n. 17
0
static bool AddLinearSystem_Poisson3D_P1(
		double alpha, double source, 
        Fem::Ls::CLinearSystem_Field& ls, 
		unsigned int id_field_val, const CFieldWorld& world,
		unsigned int id_ea)
{
//	std::cout << "Poisson3D Tet 4-point 1st order" << std::endl;

	assert( world.IsIdEA(id_ea) );
	const CElemAry& ea = world.GetEA(id_ea);
	assert( ea.ElemType() == TET );

	if( !world.IsIdField(id_field_val) ) return false;
	const CField& field_val = world.GetField(id_field_val);

	const CElemAry::CElemSeg& es_c = field_val.GetElemSeg(id_ea,CORNER,false,world);

	const unsigned int nno = 4;
	const unsigned int ndim = 3;

	unsigned int no_c[nno];	// 要素節点の全体節点番号

	double value_c[nno];		// 要素節点の値
	double coord_c[nno][ndim];	// 要素節点の座標
			
	double emat[nno][nno];	// 要素剛性行列
	double eres_c[nno];	// 要素節点等価内力、外力、残差ベクトル
				
	CMatDia_BlkCrs& mat_cc = ls.GetMatrix(  id_field_val,CORNER,world);
	CVector_Blk&    res_c  = ls.GetResidual(id_field_val,CORNER,world);

	const CNodeAry::CNodeSeg& ns_c_val = field_val.GetNodeSeg(CORNER,true,world);
	const CNodeAry::CNodeSeg& ns_c_co  = field_val.GetNodeSeg(CORNER,false,world);

	for(unsigned int ielem=0;ielem<ea.Size();ielem++)
	{
		// 要素配列から要素セグメントの節点番号を取り出す
		es_c.GetNodes(ielem,no_c);
		// 節点の値を取って来る
		for(unsigned int inoes=0;inoes<nno;inoes++){
			ns_c_co.GetValue(no_c[inoes],coord_c[inoes]);
			ns_c_val.GetValue(no_c[inoes],&value_c[inoes]);
		}

		// 面積を求める
		const double vol = TetVolume(coord_c[0],coord_c[1],coord_c[2], coord_c[3]);
		// 形状関数の微分を求める	
		double dldx[nno][ndim];	// 形状関数のxy微分
		double const_term[nno];	// 形状関数の定数項
		TetDlDx(dldx,const_term,coord_c[0],coord_c[1],coord_c[2], coord_c[3]);
		// 要素剛性行列を作る
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			emat[ino][jno] = alpha*vol*(dldx[ino][0]*dldx[jno][0]+dldx[ino][1]*dldx[jno][1]+dldx[ino][2]*dldx[jno][2]);
		}
		}
		// 要素節点等価外力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
			eres_c[ino] = source*vol*0.25;
		}
		// 要素節点等価内力ベクトルを求める
		for(unsigned int ino=0;ino<nno;ino++){
		for(unsigned int jno=0;jno<nno;jno++){
			eres_c[ino] -= emat[ino][jno]*value_c[jno];
		}	
		}
		// 要素剛性行列にマージする
		mat_cc.Mearge(nno,no_c,nno,no_c,1,&emat[0][0]);
		// 残差ベクトルにマージする
		for(unsigned int inoes=0;inoes<nno;inoes++){
			res_c.AddValue( no_c[inoes],0,eres_c[inoes]);
		}
	}
	return true;
}