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 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. 4
0
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;
}
void Ls::CLinearSystem_RigidField2::SetRigidSystem(const std::vector<Rigid::CRigidBody3D>& aRB, 
                                                   const std::vector<Rigid::CConstraint*>& aConst)
{   
  //    std::cout << "0ls : set rigid system" << std::endl;
  assert( m_ls.GetNLinSysSeg() == this->m_aSegRF.size() );
  ilss_rigid = m_ls.GetNLinSysSeg();
  const unsigned int nRB = aRB.size();
  const unsigned int nConst = aConst.size();
  m_aSegRF.push_back( CLinSysSegRF(nRB,nConst) );
  
  const unsigned int nblk = nRB+nConst;
  {
    std::vector<unsigned int> aBlkSize;
    aBlkSize.resize(nblk);
    for(unsigned int irb=0;irb<nRB;irb++){
      aBlkSize[irb] = aRB[irb].GetDOF();
    }
    for(unsigned int icst=0;icst<nConst;icst++){
      aBlkSize[nRB+icst] = aConst[icst]->GetDOF();
    }
    const int ires = m_ls.AddLinSysSeg(nblk,aBlkSize);
    assert( ires == ilss_rigid );
  }
  Com::CIndexedArray crs;
  {
    crs.index.clear();
    crs.index.resize(nblk+1,0);
    crs.index[0] = 0;
    for(unsigned int i=0;i<nRB;i++){ crs.index[i+1]=0; }
    for(unsigned int i=nRB;i<nRB+nConst;i++){ crs.index[i+1]=0; }
    for(unsigned int icst=0;icst<nConst;icst++){
      const std::vector<unsigned int>& aIndRB = aConst[icst]->GetAry_IndexRB();
      for(unsigned int i=0;i<aIndRB.size();i++){
        const unsigned int irb0 = aIndRB[i];
        crs.index[irb0+1] += 1;
      }
      crs.index[icst+nRB+1] += aIndRB.size();
    }
    for(unsigned int i=0;i<nblk;i++){ 
      crs.index[i+1] = crs.index[i+1] + crs.index[i];
    }
    const unsigned int ncrs = crs.index[nblk];
    crs.array.resize(ncrs);
    for(unsigned int icst=0;icst<nConst;icst++){
      const std::vector<unsigned int>& aIndRB = aConst[icst]->GetAry_IndexRB();
      for(unsigned int i=0;i<aIndRB.size();i++){
        const unsigned int irb0 = aIndRB[i];
        const unsigned int icrs0 = crs.index[icst+nRB];
        crs.array[icrs0] = irb0;
        crs.index[icst+nRB] += 1;
        const unsigned int icrs1 = crs.index[irb0];
        crs.array[icrs1] = icst+nRB;
        crs.index[irb0] += 1;
      }
    }
    for(int i=nblk;i>0;i--){ 
      crs.index[i] = crs.index[i-1];
    }
    crs.index[0] = 0;
    crs.Sort();
    assert( crs.index[nRB+nConst] == ncrs );
  }
  m_ls.AddMat_Dia(ilss_rigid,crs);  
}
// 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;
}