bool CZLinearSystem::AddMat_Dia(unsigned int ils, const CElemAry& ea, unsigned int id_es) { assert( ils < m_aSeg.size() ); assert( ea.IsSegID(id_es) ); { // 行列がなければ作るよ const CElemAry::CElemSeg& es = ea.GetSeg(id_es); const unsigned int nnode = m_aSeg[ils].nnode; const unsigned int len = m_aSeg[ils].len; assert( es.GetMaxNoes() < nnode ); if( m_Matrix_Dia[ils] == 0 ){ m_Matrix_Dia[ils] = new CZMatDia_BlkCrs(nnode,len); } else{ // assertする assert( m_Matrix_Dia[ils]->NBlkMatCol() == nnode ); assert( m_Matrix_Dia[ils]->LenBlkCol() == len ); assert( m_Matrix_Dia[ils]->NBlkMatRow() == nnode ); assert( m_Matrix_Dia[ils]->LenBlkRow() == len ); } } Com::CIndexedArray crs; ea.MakePattern_FEM(id_es,crs); assert( crs.CheckValid() ); m_Matrix_Dia[ils]->AddPattern(crs); return true; }
bool CZLinearSystem::AddMat_NonDia(unsigned int ils_col, unsigned int ils_row, const Com::CIndexedArray& crs ) { assert( ils_col < m_aSeg.size() ); assert( ils_row < m_aSeg.size() ); { const unsigned int nnode_col = m_aSeg[ils_col].nnode; const unsigned int len_col = m_aSeg[ils_col].len; const unsigned int nnode_row = m_aSeg[ils_row].nnode; const unsigned int len_row = m_aSeg[ils_row].len; if( m_Matrix_NonDia[ils_col][ils_row] == 0 ){ m_Matrix_NonDia[ils_col][ils_row] = new CZMat_BlkCrs(nnode_col,len_col, nnode_row,len_row); } else{ assert( m_Matrix_NonDia[ils_col][ils_row]->NBlkMatCol() == nnode_col ); assert( m_Matrix_NonDia[ils_col][ils_row]->LenBlkCol() == len_col ); assert( m_Matrix_NonDia[ils_col][ils_row]->NBlkMatRow() == nnode_row ); assert( m_Matrix_NonDia[ils_col][ils_row]->LenBlkRow() == len_row ); } } assert( crs.CheckValid() ); m_Matrix_NonDia[ils_col][ils_row]->AddPattern(crs); return true; }
bool MatVec::CMat_BlkCrs::AddPattern(const Com::CIndexedArray& crs) { // 入力チェック if( !crs.CheckValid() ) return false; if( crs.Size() > NBlkMatCol() ) return false; { unsigned int max_val = 0; for(unsigned int i=0;i<crs.array.size();i++){ max_val = (max_val>crs.array[i])?max_val:crs.array[i]; } if( max_val>NBlkMatRow() ) return false; } if( crs.array.size() == 0 ) return true; if( m_ncrs_Blk == 0 ){ this->DeletePattern(); assert( m_colInd_Blk != 0 ); const unsigned int nblk = NBlkMatCol(); { const unsigned int nblk_crs = crs.Size(); for(unsigned int iblk=0;iblk<nblk_crs+1;iblk++){ m_colInd_Blk[iblk] = crs.index[iblk]; } for(unsigned int iblk=nblk_crs+1;iblk<nblk+1;iblk++){ m_colInd_Blk[iblk] = crs.index[nblk_crs]; } } // for(unsigned int iblk=0;iblk<nblk+1;iblk++){ m_colInd_Blk[iblk] = crs.index[iblk]; } const unsigned int ncrs = m_colInd_Blk[nblk]; assert( m_rowPtr_Blk == 0 ); assert( crs.array.size() >= ncrs ); m_rowPtr_Blk = new unsigned int [ncrs]; for(unsigned int icrs=0;icrs<ncrs;icrs++){ m_rowPtr_Blk[icrs] = crs.array[icrs]; } m_ncrs_Blk = ncrs; // for(unsigned int iblk=0;iblk<nblk;iblk++){ // std::cout << iblk << "-->"; // for(unsigned int icrs=m_colInd_Blk[iblk];icrs<m_colInd_Blk[iblk+1];icrs++){ // std::cout << m_rowPtr_Blk[icrs] << " "; // } // std::cout << std::endl; // } return true; } bool is_included = true; { // この要素が行列に含まれているかどうか調べる int* tmp_buffer = new int [this->NBlkMatRow()]; for(unsigned int iblk=0;iblk<this->NBlkMatRow();iblk++){ tmp_buffer[iblk] = 0; } // const unsigned int ncrs_size = crs.size; for(unsigned int iblk=0;iblk<crs.Size();iblk++){ // 既に要素が入っている場所にフラグを立てる for(unsigned int icrs=m_colInd_Blk[iblk];icrs<m_colInd_Blk[iblk+1];icrs++){ unsigned int jnode = m_rowPtr_Blk[icrs]; tmp_buffer[jnode] = 1; } // パターンが適合しているかどうか調べる for(unsigned int icrs=crs.index[iblk];icrs<crs.index[iblk+1];icrs++){ unsigned int jnode = crs.array[icrs]; if( tmp_buffer[jnode] != 1 ){ is_included = false; break; } } if( !is_included ) break; // フラグを元に戻す for(unsigned int icrs=m_colInd_Blk[iblk];icrs<m_colInd_Blk[iblk+1];icrs++){ unsigned int jnode = m_rowPtr_Blk[icrs]; tmp_buffer[jnode] = 0; } if( !is_included ) break; } delete[] tmp_buffer; } if( is_included ) return true; // パターンを追加する std::vector<unsigned int> tmp_row_ptr; tmp_row_ptr.reserve(crs.Size()+this->NCrs()); { // とりあえずこのtmp_row_ptrを作ってから、コピーする int* tmp_buffer = new int [this->NBlkMatRow()]; for(unsigned int iblk=0;iblk>NBlkMatRow();iblk++){ tmp_buffer[iblk] = 0; } for(unsigned int iblk=0;iblk<NBlkMatCol();iblk++){ // unsigned int icrs_i = tmp_row_ptr.size(); for(unsigned int icrs=m_colInd_Blk[iblk];icrs<m_colInd_Blk[iblk+1];icrs++){ unsigned int jblk = m_rowPtr_Blk[icrs]; if( tmp_buffer[jblk] != (int)iblk+1 ){ tmp_row_ptr.push_back(jblk); tmp_buffer[jblk] = iblk+1; } } if( iblk < crs.Size() ){ // ここは忘れがちで注意が必要 for(unsigned int icrs=crs.index[iblk];icrs<crs.index[iblk+1];icrs++){ unsigned int jblk = crs.array[icrs]; if( tmp_buffer[jblk] != (int)iblk+1 ){ tmp_row_ptr.push_back(jblk); tmp_buffer[jblk] = iblk+1; } } } m_colInd_Blk[iblk] = tmp_row_ptr.size(); } delete[] tmp_buffer; } for(unsigned int iblk=NBlkMatCol();iblk>0;iblk--){ m_colInd_Blk[iblk] = m_colInd_Blk[iblk-1]; } m_colInd_Blk[0] = 0; delete[] m_rowPtr_Blk; m_ncrs_Blk = m_colInd_Blk[NBlkMatCol()]; m_rowPtr_Blk = new unsigned int [m_ncrs_Blk]; for(unsigned int icrs=0;icrs<m_ncrs_Blk;icrs++){ m_rowPtr_Blk[icrs] = tmp_row_ptr[icrs]; } // row_ptrを昇順にバブルソートする for(unsigned int iblk=0;iblk<NBlkMatCol();iblk++){ const unsigned int is_crs = m_colInd_Blk[iblk ]; const unsigned int ie_crs = m_colInd_Blk[iblk+1]; if( is_crs == ie_crs ) continue; assert( is_crs < ie_crs ); int itmp; for(unsigned int icrs=is_crs;icrs<ie_crs-1;icrs++){ for(unsigned int jcrs=ie_crs-1;jcrs>icrs;jcrs--){ if( m_rowPtr_Blk[jcrs] < m_rowPtr_Blk[jcrs-1] ){ itmp = m_rowPtr_Blk[jcrs]; m_rowPtr_Blk[jcrs] = m_rowPtr_Blk[jcrs-1]; m_rowPtr_Blk[jcrs-1] = itmp; } } } } 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; }
// fieldで初期化する、fieldの中の非ゼロパターンで行列を作る bool Ls::CLinearSystem_RigidField2::AddPattern_Field( unsigned int id_field1, unsigned int id_field2, const Fem::Field::CFieldWorld& world) { if( !world.IsIdField(id_field1) ) return false; const Fem::Field::CField& field1 = world.GetField(id_field1); unsigned int id_field_parent; { if( field1.GetIDFieldParent() == 0 ){ id_field_parent = id_field1; } else{ id_field_parent = field1.GetIDFieldParent(); } } const unsigned int nlen_value = field1.GetNLenValue(); int ilss_add_c; int ilss_add_b; { // Cornerセグメントを作る unsigned int id_na_val = field1.GetNodeSegInNodeAry(Fem::Field::CORNER).id_na_va; if( id_na_val != 0 ){ assert( world.IsIdNA(id_na_val) ); const Fem::Field::CNodeAry& na = world.GetNA(id_na_val); assert( m_ls.GetNLinSysSeg() == this->m_aSegRF.size() ); ilss_add_c = m_ls.GetNLinSysSeg(); this->m_aSegRF.push_back( CLinSysSegRF(id_field_parent,Fem::Field::CORNER) ); int ires = m_ls.AddLinSysSeg( na.Size(), field1.GetNLenValue() ); assert( ires == ilss_add_c ); } else{ ilss_add_c = -1; } } { // Bubbleセグメントを作る unsigned int id_na_val = field1.GetNodeSegInNodeAry(Fem::Field::BUBBLE).id_na_va; if( id_na_val != 0 ){ assert( world.IsIdNA(id_na_val) ); const Fem::Field::CNodeAry& na = world.GetNA(id_na_val); assert( m_ls.GetNLinSysSeg() == this->m_aSegRF.size() ); ilss_add_b = m_ls.GetNLinSysSeg(); this->m_aSegRF.push_back( CLinSysSegRF(id_field_parent,Fem::Field::BUBBLE) ); int ires = m_ls.AddLinSysSeg( na.Size(), field1.GetNLenValue() ); assert( ires == ilss_add_b ); } } const Fem::Field::CField& field2 = world.GetField(id_field2); const std::vector<unsigned int>& aIdEA1 = field1.GetAryIdEA(); const std::vector<unsigned int>& aIdEA2 = field2.GetAryIdEA(); for(;;){ // ダミーのfor文を使ってbreakで抜けられるようにする // Corner-Corner関係を作る if( ilss_add_c == -1 ) break; const unsigned int id_na_va1 = field1.GetNodeSegInNodeAry(Fem::Field::CORNER).id_na_va; const unsigned int id_na_co1 = field1.GetNodeSegInNodeAry(Fem::Field::CORNER).id_na_co; const unsigned int id_na_va2 = field2.GetNodeSegInNodeAry(Fem::Field::CORNER).id_na_va; const unsigned int id_na_co2 = field2.GetNodeSegInNodeAry(Fem::Field::CORNER).id_na_co; assert( aIdEA1.size() > 0 ); if( id_na_co1 != id_na_co2 ) break; for(unsigned int iiea1=0;iiea1<aIdEA1.size();iiea1++){ const unsigned int id_ea1 = aIdEA1[iiea1]; if( field1.GetIdElemSeg(id_ea1,Fem::Field::CORNER,true,world) == 0 ) continue; assert( world.IsIdEA(id_ea1) ); const Fem::Field::CElemAry& ea1 = world.GetEA(id_ea1); const unsigned int id_es_c1 = field1.GetIdElemSeg(id_ea1,Fem::Field::CORNER,true,world); assert( ea1.IsSegID(id_es_c1) ); // CORNER1-CORNER1 { Com::CIndexedArray crs; ea1.MakePattern_FEM(id_es_c1,crs); m_ls.AddMat_Dia(ilss_add_c, crs ); // cc行列を作る } //////////////// for(unsigned int iiea2=0;iiea2<aIdEA2.size();iiea2++) { const unsigned int id_ea2 = aIdEA2[iiea2]; if( id_ea1 == id_ea2 ){ // CORNER1-CORNER2 const int ils2_c = this->FindIndexArray_Seg(id_field2,Fem::Field::CORNER,world); if( ils2_c != -1 ){ assert( ils2_c >= 0 && ils2_c < this->GetNLinSysSeg() ); const unsigned int id_es_c2 = field2.GetIdElemSeg(id_ea2,Fem::Field::CORNER,true,world); assert( id_es_c1 == id_es_c2 ); Com::CIndexedArray crs; ea1.MakePattern_FEM(id_es_c1,id_es_c2,crs); assert( crs.CheckValid() ); m_ls.AddMat_NonDia(ilss_add_c,ils2_c, crs); // c1c2行列を足す const unsigned int nnode2 = m_ls.GetBlkSizeLinSeg(ils2_c); Com::CIndexedArray crs_inv; crs_inv.SetTranspose( nnode2, crs ); m_ls.AddMat_NonDia(ils2_c,ilss_add_c, crs_inv); // c2c1行列を足す } // CORNER1-BUBBLE2 const int ils2_b = this->FindIndexArray_Seg(id_field2,Fem::Field::BUBBLE,world); if( ils2_b != -1 ){ assert(0); } } else{ const Fem::Field::CNodeAry& na1 = world.GetNA(id_na_co1); const unsigned int id_es_c_co1 = field1.GetIdElemSeg(id_ea1,Fem::Field::CORNER,false,world); const unsigned int id_es_c_co2 = field2.GetIdElemSeg(id_ea2,Fem::Field::CORNER,false,world); if( na1.IsIncludeEaEs_InEaEs( std::make_pair(id_ea1,id_es_c_co1), std::make_pair(id_ea2,id_es_c_co2) ) ) { std::cout << "ea : " << id_ea1 << " is included in " << id_ea2 << std::endl; assert( ea1.IsSegID(id_es_c_co1) ); Com::CIndexedArray crs; ea1.MakePattern_FEM(id_es_c1,id_es_c1,crs); // 自分も含む assert( crs.CheckValid() ); if( field2.IsPartial() ){ std::cout << "Error!-->未実装" << std::endl; assert(0); } for(unsigned int icrs=0;icrs<crs.array.size();icrs++){ unsigned int jno_va = crs.array[icrs]; unsigned int jno_co = field1.GetMapVal2Co(jno_va); // std::cout << jno_van << " " << jno_co << std::endl; // 本当はfield2.GetMapVal2Coの逆写像を使って求める. unsigned int jno_va2 = jno_co; crs.array[icrs] = jno_va2; } int ils2 = this->FindIndexArray_Seg(id_field2,Fem::Field::CORNER,world); assert( ils2 >= 0 && ils2 < this->GetNLinSysSeg() ); // std::cout << "ils_seg : " << ils0 << " " << ils2 << std::endl; m_ls.AddMat_NonDia(ilss_add_c,ils2, crs); const unsigned int nnode2 = m_ls.GetBlkSizeLinSeg(ils2); Com::CIndexedArray crs_inv; crs_inv.SetTranspose( nnode2, crs ); m_ls.AddMat_NonDia(ils2,ilss_add_c, crs_inv); } } } } break; } for(unsigned int iiea=0;iiea<aIdEA1.size();iiea++){ const unsigned int id_ea1 = aIdEA1[iiea]; const unsigned int id_es_b1 = field1.GetIdElemSeg(id_ea1,Fem::Field::BUBBLE,true,world); if( id_es_b1 == 0 ) continue; const Fem::Field::CElemAry& ea1 = world.GetEA(id_ea1); assert( world.IsIdEA(id_ea1) ); assert( ea1.IsSegID(id_es_b1) ); const unsigned int ils0 = ilss_add_b; // BUBLE1-BUBBLE2 { Com::CIndexedArray crs; ea1.MakePattern_FEM(id_es_b1,crs); m_ls.AddMat_Dia(ilss_add_b, crs ); } const unsigned int id_ea2 = aIdEA2[iiea]; assert( id_ea1 == id_ea2 ); const unsigned int id_es_c2 = field2.GetIdElemSeg(id_ea2,Fem::Field::CORNER,true,world); assert( ea1.IsSegID(id_es_c2) ); int ils2 = this->FindIndexArray_Seg(id_field2,Fem::Field::CORNER,world); assert( ils2 >= 0 && ils2 < this->GetNLinSysSeg() ); assert( ils2 >= 0 && ils2 < m_ls.GetNLinSysSeg() ); { Com::CIndexedArray crs; ea1.MakePattern_FEM(id_es_b1,id_es_c2,crs); assert( crs.CheckValid() ); m_ls.AddMat_NonDia(ils0,ils2, crs); // b1c2行列を作る Com::CIndexedArray crs_inv; const unsigned nnode2 = m_ls.GetBlkSizeLinSeg(ils2); crs_inv.SetTranspose( nnode2, crs ); m_ls.AddMat_NonDia(ils2,ils0, crs_inv); // c2b1行列を作る } } // いろいろと追加が必要 // まずは足りない部分を要求するようになったらエラーを出す関数を実装しよう。 return true; }