Exemplo n.º 1
0
void Foam::cellShapeControlMesh::barycentricCoords
(
    const Foam::point& pt,
    barycentric& bary,
    Cell_handle& ch
) const
{
    // Use the previous cell handle as a hint on where to start searching
    // Giving a hint causes strange errors...
    ch = locate(toPoint(pt));

    if (dimension() > 2 && !is_infinite(ch))
    {
        oldCellHandle_ = ch;

        tetPointRef tet
        (
            topoint(ch->vertex(0)->point()),
            topoint(ch->vertex(1)->point()),
            topoint(ch->vertex(2)->point()),
            topoint(ch->vertex(3)->point())
        );

        bary = tet.pointToBarycentric(pt);
    }
}
Exemplo n.º 2
0
/*$TET$templet$!cpp-epilogue!*/
int main(int argc, char*argv[])
{
	templet tet(2);
	
	Parent* p=tet.new_Parent();
	Child*  c1=tet.new_Child();
	Child*  c2=tet.new_Child();

	c1->p_p(p->p_p1());
	c2->p_p(p->p_p2());

	tet.run();
	
	return 0;
}
Exemplo n.º 3
0
Foam::scalar Foam::foamyHexMeshChecks::coplanarTet
(
    Cell& c,
    const scalar tol
)
{
    tetPointRef tet
    (
        topoint(c->vertex(0)->point()),
        topoint(c->vertex(1)->point()),
        topoint(c->vertex(2)->point()),
        topoint(c->vertex(3)->point())
    );

    const scalar quality = tet.quality();

    if (quality < tol)
    {
        return quality;
    }

    return 0;

//    plane triPlane
//    (
//        topoint(c->vertex(0)->point()),
//        topoint(c->vertex(1)->point()),
//        topoint(c->vertex(2)->point())
//    );
//
//    const scalar distance = triPlane.distance(topoint(c->vertex(3)->point()));
//
//    // Check if the four points are roughly coplanar. If they are then we
//    // cannot calculate the circumcentre. Better test might be the volume
//    // of the tet.
//    if (distance < tol)
//    {
//        return 0;
//    }
//
//    return distance;
}
Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint
(
    const polyMesh& mesh,
    label fI,
    const point& nCc,
    scalar tol,
    bool report
)
{
    const faceList& pFaces = mesh.faces();
    const pointField& pPts = mesh.points();
    const vectorField& pC = mesh.cellCentres();
    const labelList& pOwner = mesh.faceOwner();

    const face& f = pFaces[fI];

    label oCI = pOwner[fI];

    const point& oCc = pC[oCI];

    List<scalar> tetQualities(2, 0.0);

    forAll(f, faceBasePtI)
    {
        scalar thisBaseMinTetQuality = VGREAT;

        const point& tetBasePt = pPts[f[faceBasePtI]];

        for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++)
        {
            label facePtI = (tetPtI + faceBasePtI) % f.size();
            label otherFacePtI = f.fcIndex(facePtI);

            {
                // owner cell tet
                label ptAI = f[facePtI];
                label ptBI = f[otherFacePtI];

                const point& pA = pPts[ptAI];
                const point& pB = pPts[ptBI];

                tetPointRef tet(oCc, tetBasePt, pA, pB);

                tetQualities[0] = tet.quality();
            }

            {
                // neighbour cell tet
                label ptAI = f[otherFacePtI];
                label ptBI = f[facePtI];

                const point& pA = pPts[ptAI];
                const point& pB = pPts[ptBI];

                tetPointRef tet(nCc, tetBasePt, pA, pB);

                tetQualities[1] = tet.quality();
            }

            if (min(tetQualities) < thisBaseMinTetQuality)
            {
                thisBaseMinTetQuality = min(tetQualities);
            }
        }

        if (thisBaseMinTetQuality > tol)
        {
            return faceBasePtI;
        }
    }
Exemplo n.º 5
0
  void OstreamGMV3DFmt::StaticData::initialize()
{
  if(archetypes == 0 || names == 0) {
    archetypes = new archetype_table;
    names      = new archetype_name_map;

    // construct tet
    int conn_tet[4*4] = {
      3,  0, 1, 2,
      3,  0, 3, 1,
      3,  0, 2, 3,
      3,  1, 3, 2
    };
    stream_grid_mask<int *> tet(4,4,conn_tet); 
    archetypes->push_back(archetype_type());
    ConstructGrid0(archetypes->back(), tet);
    (*names)[archetypes->size() -1] = "tet";
    
    // construct hex
    
    // 0: (0,0,0), 1: (1,0,0), 2: (1,1,0), 3: (0,1,0)
    // 4: (0,0,1), 5: (1,0,1), 6: (1,1,1), 7: (0,1,1)
    
    int conn_hex[5*6] = {
      4,  0, 3, 2, 1,
      4,  0, 1, 5, 4,
      4,  0, 4, 7, 3,
      4,  1, 2, 6, 5,
      4,  2, 3, 7, 6,
      4,  4, 5, 6, 7
    };
    stream_grid_mask<int *> hex(8,6,conn_hex); 
    archetypes->push_back(archetype_type());
    ConstructGrid0(archetypes->back(), hex);
    (*names)[archetypes->size()-1] = "phex8";

    // construct prism
    int conn_prism[3*5+2*4] = {
      3, 0, 1, 2,
      3, 3, 5, 4,
      4, 0, 3, 4, 1,
      4, 1, 4, 5, 2,
      4, 0, 2, 5, 3
    };
    stream_grid_mask<int *> prism(6,5,conn_prism); 
    archetypes->push_back(archetype_type());
    ConstructGrid0(archetypes->back(), prism);
    (*names)[archetypes->size()-1] = "prism";
    
    
    // construct pyramid
    int conn_pyramid[1*5+4*4] = {
      4,  4, 3, 2, 1,
      3,  0, 1, 2,
      3,  0, 2, 3,
      3,  0, 3, 4,
      3,  0, 4, 1
    };
    stream_grid_mask<int *> pyramid(5,5,conn_pyramid); 
    archetypes->push_back(archetype_type());
    ConstructGrid0(archetypes->back(), pyramid);
    (*names)[archetypes->size() -1] = "pyramid";

    //  cerr << Printer(*names) << '\n';
  }
}
Exemplo n.º 6
0
void tet_hp_cns::minvrt() {
	int i,j,k,n,tind,msgn,sgn,sind,v0;
	Array<FLT,2> spokemass;
	int last_phase, mp_phase;
	
	Array<double,1> lcl(NV), lclug(NV),lclres(NV),uavg(NV);
	Array<TinyVector<double,MXGP>,2> P(NV,NV);
	Array<TinyVector<double,MXGP>,1> u1d(NV),res1d(NV),temp1d(NV);
	Array<TinyVector<double,MXTM>,1> ucoef(NV),rcoef(NV),tcoef(NV);
	
	if (basis::tet(log2p).p > 2) {
		*gbl->log << "cns minvrt only works for p = 1 and 2" << endl;
		exit(4);
	}
	
	/* LOOP THROUGH EDGES */
	if (basis::tet(log2p).em > 0) {
		for(int eind = 0; eind<nseg;++eind) {
			/* SUBTRACT SIDE CONTRIBUTIONS TO VERTICES */         
			for (k=0; k <basis::tet(log2p).em; ++k) {
				for (i=0; i<2; ++i) {
					v0 = seg(eind).pnt(i);
					for(n=0;n<NV;++n)
						gbl->res.v(v0,n) -= basis::tet(log2p).sfmv(i,k)*gbl->res.e(eind,k,n);
				}
			}
		}		
	}
	
	gbl->res.v(Range(0,npnt-1),Range::all()) *= gbl->vprcn(Range(0,npnt-1),Range::all())*basis::tet(log2p).vdiag;

	/* LOOP THROUGH VERTICES */
	for(int i=0;i<npnt;++i){
		
		for(int n = 0; n < NV; ++n)
			lclres(n) = gbl->res.v(i,n);

		
		if(gbl->preconditioner == 0 || gbl->preconditioner == 1) {
			for(int n = 0; n < NV; ++n)
				lclug(n) = ug.v(i,n);

			switch_variables(lclug,lclres);

			for(int j=0;j<NV;++j){
				FLT lcl0 = lclres(j);
				for(int k=0;k<j;++k){
					lcl0 -= gbl->vpreconditioner(i,j,k)*lclres(k);
				}
				lclres(j) = lcl0/gbl->vpreconditioner(i,j,j);
			}
		}
		else {		
			int info,ipiv[NV];
			Array<double,2> P(NV,NV);
			
			for(int j=0;j<NV;++j)
				for(int k=0;k<NV;++k)
					P(j,k) = gbl->vpreconditioner(i,j,k);
				
			GETRF(NV, NV, P.data(), NV, ipiv, info);

			if (info != 0) {
				*gbl->log << "DGETRF FAILED FOR CNS MINVRT" << std::endl;
				sim::abort(__LINE__,__FILE__,gbl->log);
			}
			
			char trans[] = "T";
			GETRS(trans,NV,1,P.data(),NV,ipiv,lclres.data(),NV,info);
		}
		
		for(int n = 0; n < NV; ++n)
			gbl->res.v(i,n) = lclres(n);
		
	}
	
	for(last_phase = false, mp_phase = 0; !last_phase; ++mp_phase) {
		pc0load(mp_phase,gbl->res.v.data());
		pmsgpass(boundary::all_phased,mp_phase,boundary::symmetric);
		last_phase = true;
		last_phase &= pc0wait_rcv(mp_phase,gbl->res.v.data());
	}

	/* APPLY VERTEX DIRICHLET B.C.'S */
	for(i=0;i<nfbd;++i)
		hp_fbdry(i)->vdirichlet();
	
	for(i=0;i<nebd;++i)
		hp_ebdry(i)->vdirichlet3d();        
	
	for(i=0;i<nvbd;++i)
		hp_vbdry(i)->vdirichlet3d();
	
	if(basis::tet(log2p).em == 0) return;
	
	/* LOOP THROUGH SIDES */    
	for(int sind=0;sind<nseg;++sind) {
		
		for(int n = 0; n < NV; ++n)
			lclres(n) = gbl->res.e(sind,0,n);

		Array<FLT,2> P(NV,NV);
		for(int j=0;j<NV;++j){
			for(int k=0;k<NV;++k){
				P(j,k) = gbl->epreconditioner(sind,j,k);
				//P(j,k) = 0.5*(gbl->vpreconditioner(seg(sind).pnt(0),j,k)+gbl->vpreconditioner(seg(sind).pnt(1),j,k));
			}
		}

		if(gbl->preconditioner == 0 || gbl->preconditioner == 1) {
			for(int n = 0; n < NV; ++n)
				uavg(n) = 0.5*(ug.v(seg(sind).pnt(0),n)+ug.v(seg(sind).pnt(1),n));
				
			switch_variables(uavg,lclres);
			
			for(int j=0;j<NV;++j){
				FLT lcl0 = lclres(j);
				for(int k=0;k<j;++k){
					lcl0 -= P(j,k)*lclres(k);
				}
				lclres(j) = lcl0/P(j,j);
			}
		}
		else {
			int info,ipiv[NV];
			
			GETRF(NV, NV, P.data(), NV, ipiv, info);
			
			if (info != 0) {
				*gbl->log << "DGETRF FAILED FOR CNS MINVRT EDGE" << std::endl;
				sim::abort(__LINE__,__FILE__,gbl->log);
			}
			
			char trans[] = "T";
			GETRS(trans,NV,1,P.data(),NV,ipiv,lclres.data(),NV,info);
		}
		
		for(int n = 0; n < NV; ++n)
			gbl->res.e(sind,0,n) = lclres(n);
		
	}
	
	/* REMOVE VERTEX CONTRIBUTION FROM SIDE MODES */
	/* SOLVE FOR SIDE MODES */
	/* PART 1 REMOVE VERTEX CONTRIBUTIONS */
	for(tind=0;tind<ntet;++tind) {         
		for(i=0;i<4;++i) {
			v0 = tet(tind).pnt(i);
			for(n=0;n<NV;++n)
				uht(n)(i) = gbl->res.v(v0,n)*gbl->iprcn(tind,n);
		}
		/* edges */
		for(i=0;i<6;++i) {
			sind = tet(tind).seg(i);
			sgn  = tet(tind).sgn(i);
			for(j=0;j<4;++j) {
				msgn = 1;
				for(k=0;k<basis::tet(log2p).em;++k) {
					for(n=0;n<NV;++n)
						gbl->res.e(sind,k,n) -= msgn*basis::tet(log2p).vfms(j,4+k+i*basis::tet(log2p).em)*uht(n)(j);
					msgn *= sgn;
				}
			}
		}				
	}
	
	
	basis::tet(log2p).ediag(0) = 100.0;//for fast convergence 
	//basis::tet(log2p).ediag(0) = 48.0; //for accuracy mass lumped edge modes
	gbl->res.e(Range(0,nseg-1),0,Range::all()) *= gbl->eprcn(Range(0,nseg-1),Range::all())*basis::tet(log2p).ediag(0);
	
	for(last_phase = false, mp_phase = 0; !last_phase; ++mp_phase) {
		sc0load(mp_phase,gbl->res.e.data(),0,0,gbl->res.e.extent(secondDim));
		smsgpass(boundary::all_phased,mp_phase,boundary::symmetric);
		last_phase = true;
		last_phase &= sc0wait_rcv(mp_phase,gbl->res.e.data(),0,0,gbl->res.e.extent(secondDim));
	}
	
	/* APPLY DIRCHLET B.C.S TO MODE */
	for(int i=0;i<nfbd;++i)
		hp_fbdry(i)->edirichlet();
	
	for (int i=0;i<nebd;++i) 
		hp_ebdry(i)->edirichlet3d();	
	
	return;
}
Exemplo n.º 7
0
void tet_hp::mg_prolongate() {
	int i,j,ind,tind;
	int last_phase, mp_phase;
	
	if(!coarse_level) {
		++log2p;
		if (log2p == log2pmax) coarse_flag = false;
		return;
	}
		
//    if (mmovement == coupled_deformable) {
//        r_tet_mesh::mg_prolongate();
//    }

	for(i=0;i<nfbd;++i)
		hp_fbdry(i)->mg_prolongate();


	/* CALCULATE CORRECTIONS */
	vug_frst(Range(0,npnt-1),Range::all()) -= ug.v(Range(0,npnt-1),Range::all());

#ifdef DEBUG
	*gbl->log << vug_frst(Range(0,npnt-1),Range::all());
#endif

	/* LOOP THROUGH FINE VERTICES    */
	/* TO DETERMINE CHANGE IN SOLUTION */   
	tet_hp *fmesh = dynamic_cast<tet_hp *>(fine);
	int fnvrtx = fmesh->npnt;
	for(i=0;i<fnvrtx;++i) {
		tind = fmesh->ccnnct(i).tet;

		gbl->res.v(i,Range::all()) = 0.0;
		
		for(j=0;j<4;++j) {
			ind = tet(tind).pnt(j);
			gbl->res.v(i,Range::all()) -= fmesh->ccnnct(i).wt(j)*vug_frst(ind,Range::all());
		}
	}
	
#ifdef DEBUG
	*gbl->log << gbl->res.v(Range(0,fnvrtx-1),Range::all());
#endif
	
	for(last_phase = false, mp_phase = 0; !last_phase; ++mp_phase) {
		for(i=0;i<nfbd;++i)
			fmesh->fbdry(i)->ploadbuff(boundary::partitions,(FLT *) gbl->res.v.data(),0,NV-1,NV);

		for(i=0;i<nfbd;++i) 
			fmesh->fbdry(i)->comm_prepare(boundary::partitions,mp_phase,boundary::symmetric);

		for(i=0;i<nfbd;++i) 
			fmesh->fbdry(i)->comm_exchange(boundary::partitions,mp_phase,boundary::symmetric);

		last_phase = true;
		for(i=0;i<nfbd;++i) {
			last_phase &= fmesh->fbdry(i)->comm_wait(boundary::partitions,mp_phase,boundary::symmetric);
			fmesh->fbdry(i)->pfinalrcv(boundary::partitions,mp_phase,boundary::symmetric,boundary::average,(FLT *) gbl->res.v.data(),0,NV-1,NV);
		}
	}

	/* ADD CORRECTION */
	fmesh->ug.v(Range(0,fnvrtx-1),Range::all()) += gbl->res.v(Range(0,fnvrtx-1),Range::all());      

	return;
}
Exemplo n.º 8
0
void tet_hp::tobasis(init_bdry_cndtn *ibc, int tlvl) {
	int tind,i,j,k,m,n,v0,v1,eind,find;
	TinyVector<FLT,3> pt;
	int stridey = MXGP;
	int stridex = MXGP*MXGP; 
		
		
	/* LOOP THROUGH VERTICES */
	for(i=0;i<npnt;++i)
		for(n=0;n<NV;++n)
			ugbd(tlvl).v(i,n) = ibc->f(n,pnts(i),gbl->time);

	if (basis::tet(log2p).em == 0) return;

	/* LOOP THROUGH EDGES */   
	for(eind = 0; eind < nseg; ++eind) {

		v0 = seg(eind).pnt(0);
		v1 = seg(eind).pnt(1);
		
		if (seg(eind).info < 0){
			for(n=0;n<ND;++n)
				basis::tet(log2p).proj1d(pnts(v0)(n),pnts(v1)(n),&crd1d(n)(0));
		}
		else {
			crdtocht1d(eind,tlvl);
			for(n=0;n<ND;++n)
				basis::tet(log2p).proj1d(&cht(n)(0),&crd1d(n)(0));
		}
		
		for(n=0;n<NV;++n)
			basis::tet(log2p).proj1d(ugbd(tlvl).v(v0,n),ugbd(tlvl).v(v1,n),&u1d(n)(0));

		for(i=0;i<basis::tet(log2p).gpx; ++i) {
			pt(0) = crd1d(0)(i);
			pt(1) = crd1d(1)(i);
			pt(2) = crd1d(2)(i);
			for(n=0;n<NV;++n){
				// difference between actual function and linear 
				u1d(n)(i) -= ibc->f(n,pt,gbl->time);
			}
		}

		for(n=0;n<NV;++n)
			basis::tet(log2p).intgrt1d(&lf(n)(0),&u1d(n)(0));
		 
		for(n=0;n<NV;++n) {
			for(m=0;m<basis::tet(log2p).em;++m){ 
				ugbd(tlvl).e(eind,m,n) = -lf(n)(2+m)*basis::tet(log2p).diag1d(m);
			}
		}
	}
	
	if (basis::tet(log2p).fm == 0) return;
	
	/* LOOP THROUGH FACES */
	for(find = 0; find < ntri; ++find) {
		ugtouht2d_bdry(find,tlvl);
		for(n=0;n<NV;++n)
			basis::tet(log2p).proj2d_bdry(&uht(n)(0),&u2d(n)(0)(0),stridey);

		if (tri(find).info < 0) {
			for(n=0;n<ND;++n)
				basis::tet(log2p).proj2d(vrtxbd(tlvl)(tri(find).pnt(0))(n),vrtxbd(tlvl)(tri(find).pnt(1))(n),vrtxbd(tlvl)(tri(find).pnt(2))(n),&crd2d(n)(0)(0),stridey);
				
		}
		else {
			crdtocht2d(find,tlvl);
			for(n=0;n<ND;++n)
				basis::tet(log2p).proj2d_bdry(&cht(n)(0),&crd2d(n)(0)(0),stridey);
		}
			
		for (i=0; i < basis::tet(log2p).gpx; ++i ) {
			for (j=0; j < basis::tet(log2p).gpy; ++j ) {
				pt(0) = crd2d(0)(i)(j);
				pt(1) = crd2d(1)(i)(j);
				pt(2) = crd2d(2)(i)(j);
				for(n=0;n<NV;++n) {
					u2d(n)(i)(j) -= ibc->f(n,pt,gbl->time);
				}
			}
		}
	  

		for(n=0;n<NV;++n) {
			basis::tet(log2p).intgrt2d(&lf(n)(0),&u2d(n)(0)(0),stridey);
			for(i=0;i<basis::tet(log2p).fm;++i){
				ugbd(tlvl).f(find,i,n) = -lf(n)(3+3*basis::tet(log2p).em+i)*basis::tet(log2p).diag2d(i);
			}
		}
	}

	if (basis::tet(log2p).im == 0) return;
	
	/* LOOP THROUGH TETS */
	for(tind = 0; tind < ntet; ++tind) {
		ugtouht_bdry(tind,tlvl);
		for(n=0;n<NV;++n)
			basis::tet(log2p).proj_bdry(&uht(n)(0),&u(n)(0)(0)(0),stridex,stridey);
			
		if (tet(tind).info < 0) {
			for(n=0;n<ND;++n)
				basis::tet(log2p).proj(vrtxbd(tlvl)(tet(tind).pnt(0))(n),vrtxbd(tlvl)(tet(tind).pnt(1))(n),vrtxbd(tlvl)(tet(tind).pnt(2))(n),vrtxbd(tlvl)(tet(tind).pnt(3))(n),&crd(n)(0)(0)(0),stridex,stridey);
		}
		else {
			crdtocht(tind,tlvl);
			for(n=0;n<ND;++n)
				basis::tet(log2p).proj_bdry(&cht(n)(0),&crd(n)(0)(0)(0),stridex,stridey);
		}
			
		for (i=0; i < basis::tet(log2p).gpx; ++i ) {
			for (j=0; j < basis::tet(log2p).gpy; ++j ) {
				for (k=0; k < basis::tet(log2p).gpz; ++k ) {
					pt(0) = crd(0)(i)(j)(k);
					pt(1) = crd(1)(i)(j)(k);
					pt(2) = crd(2)(i)(j)(k);
					for(n=0;n<NV;++n)
						u(n)(i)(j)(k) -= ibc->f(n,pt,gbl->time);
				}
			}
		}

		for(n=0;n<NV;++n) {
			basis::tet(log2p).intgrt(&lf(n)(0),&u(n)(0)(0)(0),stridex,stridey);
			for(i=0;i<basis::tet(log2p).im;++i) {
				ugbd(tlvl).i(tind,i,n) = -lf(n)(basis::tet(log2p).bm+i)*basis::tet(log2p).diag3d(i);
			}
		}
	}
	
	return;
}   
Exemplo n.º 9
0
void TauWriter::operate()
{
  try {
    QFileInfo file_info(GuiMainWindow::pointer()->getFilename());
    readOutputFileName(file_info.completeBaseName() + ".grid");
    if (isValid()) {
      QString file_name = getFileName();
      NcFile *nc_file = new NcFile(file_name.toAscii(), NcFile::Replace);
      if (!nc_file->is_valid()) {
        EG_ERR_RETURN("unable to open NetCFD file for writing");
      }

      // point coordinates
      size_t Np = m_Grid->GetNumberOfPoints();
      vector<double> x(Np),y(Np),z(Np);
      for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
        vec3_t xv;
        m_Grid->GetPoint(id_node, xv.data());
        x[id_node] = xv[0];
        y[id_node] = xv[1];
        z[id_node] = xv[2];
      }
      NcDim *no_of_points = nc_file->add_dim("no_of_points", Np);
      NcVar *points_xc = nc_file->add_var("points_xc", ncDouble, no_of_points);
      NcVar *points_yc = nc_file->add_var("points_yc", ncDouble, no_of_points);
      NcVar *points_zc = nc_file->add_var("points_zc", ncDouble, no_of_points);
      points_xc->put(&x[0],Np);
      points_yc->put(&y[0],Np);
      points_zc->put(&z[0],Np);

      // boundary faces
      size_t Nbe   = 0;;
      size_t Nquad = 0;
      size_t Ntri  = 0;
      for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
        if (isSurface(id_cell, m_Grid)) {
          ++Nbe;
          if (m_Grid->GetCellType(id_cell) == VTK_TRIANGLE) {
            ++Ntri;
          } else if (m_Grid->GetCellType(id_cell) == VTK_QUAD) {
            ++Nquad;
          } else {
            EG_ERR_RETURN("unsupported boundary element type encountered");
          }
        }
      }
      NcDim *no_of_surfaceelements = nc_file->add_dim("no_of_surfaceelements", Nbe);
      NcVar *boundarymarker_of_surfaces = nc_file->add_var("boundarymarker_of_surfaces", ncInt, no_of_surfaceelements);
      vector<int> bm(Nbe,0), tri(3*Ntri), quad(4*Nquad);
      int i_bm = 0;
      QSet<int> bc_set = getAllBoundaryCodes(m_Grid);
      QVector<int> bcs(bc_set.size());
      qCopy(bc_set.begin(), bc_set.end(), bcs.begin());
      EG_VTKDCC(vtkIntArray, cell_code, m_Grid, "cell_code");
      if (Ntri) {
        NcDim *no_of_surfacetriangles = nc_file->add_dim("no_of_surfacetriangles", Ntri);
        NcDim *points_per_surfacetriangle = nc_file->add_dim("points_per_surfacetriangle", 3);
        NcVar *points_of_surfacetriangles = nc_file->add_var("points_of_surfacetriangles", ncInt, no_of_surfacetriangles, points_per_surfacetriangle);
        int i_tri = 0;
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (isSurface(id_cell, m_Grid)) {
            if (m_Grid->GetCellType(id_cell) == VTK_TRIANGLE) {
              for (int i_bc = 0; i_bc < bcs.size(); ++i_bc) {
                if (bcs[i_bc] == cell_code->GetValue(id_cell)) {
                  bm[i_bm] = i_bc+1;
                  break;
                }
              }
              vtkIdType N_pts, *pts;
              m_Grid->GetCellPoints(id_cell, N_pts, pts);
              tri[i_tri + 0] = pts[0];
              tri[i_tri + 1] = pts[1];
              tri[i_tri + 2] = pts[2];
              ++i_bm;
              i_tri += 3;
            }
          }
        }
        points_of_surfacetriangles->put(&tri[0],Ntri,3);
      }
      if (Nquad) {
        NcDim *no_of_surfacequadrilaterals     = nc_file->add_dim("no_of_surfacequadrilaterals",Nquad);
        NcDim *points_per_surfacequadrilateral = nc_file->add_dim("points_per_surfacequadrilateral",4);
        NcVar *points_of_surfacequadrilaterals = nc_file->add_var("points_of_surfacequadrilaterals",ncInt, no_of_surfacequadrilaterals, points_per_surfacequadrilateral);
        int i_quad = 0;
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (isSurface(id_cell, m_Grid)) {
            if (m_Grid->GetCellType(id_cell) == VTK_QUAD) {
              for (int i_bc = 0; i_bc < bcs.size(); ++i_bc) {
                if (bcs[i_bc] == cell_code->GetValue(id_cell)) {
                  bm[i_bm] = i_bc+1;
                  break;
                }
              }
              vtkIdType N_pts, *pts;
              m_Grid->GetCellPoints(id_cell, N_pts, pts);
              quad[i_quad + 0] = pts[0];
              quad[i_quad + 1] = pts[1];
              quad[i_quad + 2] = pts[2];
              quad[i_quad + 3] = pts[3];
              ++i_bm;
              i_quad += 4;
            }
          }
        }
        points_of_surfacequadrilaterals->put(&quad[0],Nquad,4);
      }
      boundarymarker_of_surfaces->put(&bm[0],Nbe);
      NcDim *no_of_markers = nc_file->add_dim("no_of_markers", bcs.size());


      int Ntet = 0;
      int Npri = 0;
      int Nhex = 0;
      int Npyr = 0;
      for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
        if (m_Grid->GetCellType(id_cell) == VTK_TETRA)      ++Ntet;
        if (m_Grid->GetCellType(id_cell) == VTK_PYRAMID)    ++Npyr;
        if (m_Grid->GetCellType(id_cell) == VTK_WEDGE)      ++Npri;
        if (m_Grid->GetCellType(id_cell) == VTK_HEXAHEDRON) ++Nhex;
      }

      vector<int> tet(Ntet*4),pyr(Npyr*5),pri(Npri*6),hex(Nhex*8);
      int i_tet = 0;
      int i_pyr = 0;
      int i_pri = 0;
      int i_hex = 0;
      if (Ntet) {
        NcDim *no_of_tetraeders = nc_file->add_dim("no_of_tetraeders",Ntet);
        NcDim *points_per_tetraeder = nc_file->add_dim("points_per_tetraeder",4);
        NcVar *points_of_tetraeders = nc_file->add_var("points_of_tetraeders",ncInt, no_of_tetraeders, points_per_tetraeder);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_TETRA) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            tet[i_tet + 0] = pts[0];
            tet[i_tet + 1] = pts[1];
            tet[i_tet + 2] = pts[2];
            tet[i_tet + 3] = pts[3];
            i_tet += 4;
          }
        }
        points_of_tetraeders->put(&tet[0],Ntet,4);
      }
      if (Npyr) {
        NcDim *no_of_pyramids = nc_file->add_dim("no_of_pyramids",Npyr);
        NcDim *points_per_pyramid = nc_file->add_dim("points_per_pyramid",5);
        NcVar *points_of_pyramids = nc_file->add_var("points_of_pyramids",ncInt, no_of_pyramids, points_per_pyramid);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_PYRAMID) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            pyr[i_pyr + 0] = pts[0];
            pyr[i_pyr + 1] = pts[1];
            pyr[i_pyr + 2] = pts[2];
            pyr[i_pyr + 3] = pts[3];
            pyr[i_pyr + 4] = pts[4];
            i_pyr += 5;
          }
        }
        points_of_pyramids->put(&pyr[0],Npyr,5);
      }
      if (Npri) {
        NcDim *no_of_prisms = nc_file->add_dim("no_of_prisms",Npri);
        NcDim *points_per_prism = nc_file->add_dim("points_per_prism",6);
        NcVar *points_of_prisms = nc_file->add_var("points_of_prisms",ncInt, no_of_prisms,  points_per_prism);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_WEDGE) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            pri[i_pri + 0] = pts[0];
            pri[i_pri + 1] = pts[2];
            pri[i_pri + 2] = pts[1];
            pri[i_pri + 3] = pts[3];
            pri[i_pri + 4] = pts[5];
            pri[i_pri + 5] = pts[4];
            i_pri += 6;
          }
        }
        points_of_prisms->put(&pri[0],Npri,6);
      }
      if (Nhex) {
        NcDim *no_of_hexaeders = nc_file->add_dim("no_of_hexaeders",Nhex);
        NcDim *points_per_hexaeder = nc_file->add_dim("points_per_hexaeder",8);
        NcVar *points_of_hexaeders = nc_file->add_var("points_of_hexaeders",ncInt, no_of_hexaeders, points_per_hexaeder);
        for (vtkIdType id_cell = 0; id_cell < m_Grid->GetNumberOfCells(); ++id_cell) {
          if (m_Grid->GetCellType(id_cell) == VTK_HEXAHEDRON) {
            vtkIdType *pts, N_pts;
            m_Grid->GetCellPoints(id_cell, N_pts, pts);
            hex[i_hex + 0] = pts[4];
            hex[i_hex + 1] = pts[7];
            hex[i_hex + 2] = pts[6];
            hex[i_hex + 3] = pts[5];
            hex[i_hex + 4] = pts[0];
            hex[i_hex + 5] = pts[3];
            hex[i_hex + 6] = pts[2];
            hex[i_hex + 7] = pts[1];
            i_hex += 8;
          }
        }
        points_of_hexaeders->put(&hex[0],Nhex,8);
      }

      delete nc_file;
    }
  } catch (Error err) {
    err.display();
  }
}