static void BoundaryCondition (unsigned int id_field, const ELSEG_TYPE& elseg_type, MatVec::CBCFlag& bc_flag, const CFieldWorld& world, unsigned int ioffset=0) { if( !world.IsIdField(id_field) ) return; const Fem::Field::CField& field = world.GetField(id_field); { // Assert const unsigned int len = bc_flag.LenBlk(); assert( ioffset < len ); } const unsigned int nlen = field.GetNLenValue(); const std::vector<unsigned int>& aIdEA = field.GetAryIdEA(); for(unsigned int iea=0;iea<aIdEA.size();iea++){ unsigned int id_ea = aIdEA[iea]; const CElemAry& ea = world.GetEA(id_ea); unsigned int noes[256]; if( elseg_type == CORNER && field.GetIdElemSeg(id_ea,CORNER,true,world) != 0 ){ const Fem::Field::CElemAry::CElemSeg& es = field.GetElemSeg(id_ea,CORNER,true,world); unsigned int nnoes = es.Length(); for(unsigned int ielem=0;ielem<ea.Size();ielem++){ es.GetNodes(ielem,noes); for(unsigned int inoes=0;inoes<nnoes;inoes++){ for(unsigned int ilen=0;ilen<nlen;ilen++){ bc_flag.SetBC(noes[inoes],ilen+ioffset); } } } } if( elseg_type == BUBBLE && field.GetIdElemSeg(id_ea,BUBBLE,true,world) != 0 ){ const Fem::Field::CElemAry::CElemSeg& es = field.GetElemSeg(id_ea,BUBBLE,true,world); unsigned int nnoes = es.Length(); for(unsigned int ielem=0;ielem<ea.Size();ielem++){ es.GetNodes(ielem,noes); for(unsigned int inoes=0;inoes<nnoes;inoes++){ for(unsigned int ilen=0;ilen<nlen;ilen++){ bc_flag.SetBC(noes[inoes],ilen+ioffset); } } } } if( elseg_type == EDGE && field.GetIdElemSeg(id_ea,EDGE,true,world) != 0 ){ const Fem::Field::CElemAry::CElemSeg& es = field.GetElemSeg(id_ea,EDGE,true,world); unsigned int nnoes = es.Length(); for(unsigned int ielem=0;ielem<ea.Size();ielem++){ es.GetNodes(ielem,noes); for(unsigned int inoes=0;inoes<nnoes;inoes++){ for(unsigned int ilen=0;ilen<nlen;ilen++){ bc_flag.SetBC(noes[inoes],ilen+ioffset); } } } } } }
static void BoundaryCondition (unsigned int id_field, const ELSEG_TYPE& elseg_type, unsigned int idofns, MatVec::CBCFlag& bc_flag, const CFieldWorld& world) { if( !world.IsIdField(id_field) ) return; const Fem::Field::CField& field = world.GetField(id_field); assert( (int)idofns < bc_flag.LenBlk() ); const std::vector<unsigned int>& aIdEA = field.GetAryIdEA(); for(unsigned int iea=0;iea<aIdEA.size();iea++){ const unsigned int id_ea = aIdEA[iea]; const CElemAry& ea = world.GetEA(id_ea); if( elseg_type == CORNER && field.GetIdElemSeg(id_ea,CORNER,true,world) != 0 ){ SetBCFlagToES(id_field,bc_flag, ea, field.GetIdElemSeg(id_ea,CORNER,true,world), idofns); } if( elseg_type == BUBBLE && field.GetIdElemSeg(id_ea,BUBBLE,true,world) != 0 ){ SetBCFlagToES(id_field,bc_flag, ea, field.GetIdElemSeg(id_ea,BUBBLE,true,world), idofns); } if( elseg_type == EDGE && field.GetIdElemSeg(id_ea,EDGE, true,world) != 0 ){ SetBCFlagToES(id_field,bc_flag, ea, field.GetIdElemSeg(id_ea,EDGE, true,world), idofns); } } }
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; }
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 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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 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; }
// 対角にパターンを追加 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; }
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; }