void DGhybrid::movemesh() { int ip, ibp, idim; // now solve Delaunay -- may need to set up once again - CHECK dgm.movemesh(); // re-assemble coords for the quadratic mesh amat::Matrix<double> mqcoords(mq->gnpoin(), mq->gndim()); amat::Matrix<double> intpointsq = dgm.getInteriorPoints(); int ipoin, k = 0; // get interior points for(ipoin = 0; ipoin < mq->gnpoin(); ipoin++) if(!bounflag_q[ipoin]) { for(idim = 0; idim < mq->gndim(); idim++) mqcoords(ipoin,idim) = inpoints_q.get(k,idim); k++; } // update the backmesh coords for(ibp = 0; ibp < nbackp; ibp++) for(idim = 0; idim < mq->gndim(); idim++) backpoints(ibp,idim) += motion_b.get(ibp,idim); // get boundary points from backpoints k = 0; for(ip = 0; ip < mq->gnpoin(); ip++) if(bounflag_q.at(ip) == 1) { for(idim = 0; idim < mq->gndim(); idim++) mqcoords(ip,idim) = backpoints(k,idim); k++; } mq->setcoords(&mqcoords); bm.setcoords(&backpoints); bm.writeGmsh2("testdg_moved.msh"); }
/** \todo Currently cannot handle intersecting layer fronts from different unconnected boundaries. */ void DGhybrid::compute_backmesh_points() { std::vector<int> prevlaypo(m->gnpoin(),0); std::vector<int> curlaypo(m->gnpoin(),0); std::vector<int> layel(m->gnelem(),0); int ib, iel, j, ip, idim, ele; nbpoin_q = 0; // mark the boundary points of linear mesh, 0th layer for(ib = 0; ib < m->gnface(); ib++) { for(j = 0; j < m->gnnofa(); j++) curlaypo[m->gbface(ib,j)] = 1; } // get number of boundary points in the quadratic mesh for(ip = 0; ip < mq->gnpoin(); ip++) nbpoin_q += bounflag_q[ip]; std::cout << "DGhybrid: compute_backmesh_points(): Number of boundary points = " << nbpoin_q << ", number of layers = " << nlayers << std::endl; // for each layer, mark elements containing marked points, and then mark all points of these elements for(int ilayer = 0; ilayer < nlayers; ilayer++) { for(ip = 0; ip < m->gnpoin(); ip++) { prevlaypo[ip] = curlaypo[ip]; curlaypo[ip] = 0; } // mark elements surrounding marked points, and further mark points of these elements for(ip = 0; ip < m->gnpoin(); ip++) { if(prevlaypo[ip] == 1) { for(int iel = m->gesup_p(ip); iel < m->gesup_p(ip+1); iel++) { ele = m->gesup(iel); if(layel[ele] == 0) { layel[ele] = 1; for(j = 0; j < m->gnnode(ele); j++) if(prevlaypo[m->ginpoel(ele,j)] != 1) curlaypo[m->ginpoel(ele,j)] = 1; } } } } } // add points marked in curlaypo to layerpoints for(ip = 0; ip < m->gnpoin(); ip++) if(curlaypo[ip] == 1) layerpoints.push_back(ip); std::cout << "DGhybrid: compute_backmesh_points(): Found " << layerpoints.size() << " points in layer " << nlayers << std::endl; nbackp = nbpoin_q + layerpoints.size(); backpoints.setup(nbackp,m->gndim()); // add boundary points of the high-order mesh int k = 0; for(ip = 0; ip < mq->gnpoin(); ip++) if(bounflag_q.at(ip) == 1) { for(idim = 0; idim < mq->gndim(); idim++) backpoints(k,idim) = mq->gcoords(ip,idim); k++; } if(k != nbpoin_q) std::cout << "DGhybrid: compute_backmesh_points(): Error in getting the points!" << std::endl; // add layer points of the linear mesh for(ip = 0; ip < layerpoints.size(); ip++) for(idim = 0; idim < m->gndim(); idim++) backpoints(nbpoin_q+ip,idim) = m->gcoords(layerpoints[ip],idim); std::cout << "DGhybrid: compute_backmesh_points(): Backmesh has " << nbackp << " points." << std::endl; }
amc_int gbpsubp(amc_int i) const { return bpsubp.get(i); }
amc_int gbfsubp_p(amc_int i) const { return bfsubp_p.get(i); }
amc_int gesuel(amc_int ielem, int jnode) const { return esuel.get(ielem, jnode); }
amc_int gesup_p(amc_int i) const { return esup_p.get(i); }
amc_int gbpointsinv(amc_int ipoin) const { return bpointsinv.get(ipoin); }
int gflag_bpoin(amc_int ipoin) const { return flag_bpoin.get(ipoin); }
int gintfacbtags(int face, int i) const { return intfacbtags.get(face,i); }
int gpsup_p(int i) const { return psup_p.get(i); }
int gesup(int i) const { return esup.get(i); }
double gcoords(int pointno, int dim) const { return coords.get(pointno,dim); }
/// Generates the background mesh and computes displacements of its nodes using linear elasticity void DGhybrid::generate_backmesh_and_compute_displacements() { // make a list of interior points of the quadratic mesh int ip, ipoin, ib, ilp, idim, ninpoin_q = 0, k = 0, j; for(ipoin = 0; ipoin < mq->gnpoin(); ipoin++) ninpoin_q += bounflag_q[ipoin]; ninpoin_q = mq->gnpoin() - ninpoin_q; inpoints_q.setup(ninpoin_q, mq->gndim()); k = 0; for(ipoin = 0; ipoin < mq->gnpoin(); ipoin++) if(!bounflag_q[ipoin]) { for(idim = 0; idim < mq->gndim(); idim++) inpoints_q(k,idim) = mq->gcoords(ipoin,idim); k++; } std::cout << "DGhybrid: generate_backmesh_and_compute_displacements(): No. of interior points to move = " << inpoints_q.rows() << std::endl; // setup DGM and get backmesh dgm.setup(mq->gndim(), &inpoints_q, &backpoints, &motion_b); dgm.generateDG(); bm = dgm.getDelaunayGraph(); std::cout << "DGhybrid: Back mesh has " << bm.gnpoin() << " points, " << bm.gnelem() << " elements." << std::endl; bm.writeGmsh2("testdg.msh"); // prepare input for linear elasticity problem motion_b.setup(nbackp,m->gndim()); motion_b.zeros(); // cflags contains 1 if the corresponding backmesh point has a Dirichlet BC std::vector<int> cflags(nbackp,0); // get displacements of the boundary points of the quadratic mesh k = 0; for(ip = 0; ip < mq->gnpoin(); ip++) { if(bounflag_q[ip] == 1) { for(idim = 0; idim < mq->gndim(); idim++) { motion_b(k, idim) = b_motion_q->get(ip,idim); cflags[k] = 1; } k++; } } // setup and solve the elasticity equations to get displacement of the background mesh std::cout << "Starting linelast" << std::endl; linm.setup(&bm, lambda, mu); linm.assembleStiffnessMatrix(); linm.assembleLoadVector(); linm.dirichletBC_points(cflags, motion_b); amat::SpMatrix A = linm.stiffnessMatrix(); amat::Matrix<double> b = linm.loadVector(); amat::Matrix<double> xb(2*nbackp,1); amat::Matrix<double> x(2*nbackp,1); xb.zeros(); // TODO: add a switch to change solver x = sparseCG_d(&A, b, xb, tol, maxiter); for(int i = 0; i < nbackp; i++) for(idim = 0; idim < mq->gndim(); idim++) motion_b(i, idim) = x.get(i+idim*nbackp); }
int ginpoel(amc_int elemno, int locnode) const { return inpoel.get(elemno, locnode); }
int gbpointsb(int poin, int i) const { return bpointsb.get(poin,i); }
int gbface(amc_int faceno, int val) const { return bface.get(faceno, val); }
int gbfacebp(int iface, int i) const { return bfacebp.get(iface,i); }
amc_int gbpoints(amc_int ipoin) const { return bpoints.get(ipoin); }
int gbifmap(int intfacno) const { return bifmap.get(intfacno); }
int glpofa(amc_int iface, int ifnode) const { return lpofa.get(iface, ifnode); }
int gifbmap(int bfaceno) const { return ifbmap.get(bfaceno); }
amc_int gedgepo(amc_int iedge, int ipoin) const { return edgepo.get(iedge,ipoin); }
double gjacobians(int ielem) const { return jacobians.get(ielem,0); }
amc_int gintfac(amc_int face, int i) const { return intfac.get(face,i); }
int gflag_bpoin(const amc_int pointno) const { return flag_bpoin.get(pointno); }
amc_int gbfsubf(amc_int iface, int isurr) const { return bfsubf.get(iface,isurr); }
/// Access point coordinates amc_real gcoords(amc_int pointno, int dim) const { return coords.get(pointno,dim); }
amc_real gjacobians(amc_int ielem) const { return jacobians.get(ielem,0); }
/** Writes multiple scalar data sets and one vector data set, all cell-centered data, to a file in VTU format. * If either x or y is a 0x0 matrix, it is ignored. * \param fname is the output vtu file name */ void writeScalarsVectorToVtu_CellData(std::string fname, const amc::UMesh2d& m, const amat::Matrix<double>& x, std::string scaname[], const amat::Matrix<double>& y, std::string vecname) { int elemcode = 5; if(m.gnnode() == 4) elemcode = 9; else if(m.gnnode() == 6) elemcode = 22; else if(m.gnnode() == 8) elemcode = 23; else if(m.gnnode() == 9) elemcode = 28; std::cout << "aoutput: Writing vtu output...\n"; std::ofstream out(fname); int nscalars = x.cols(); out << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n"; out << "<UnstructuredGrid>\n"; out << "\t<Piece NumberOfPoints=\"" << m.gnpoin() << "\" NumberOfCells=\"" << m.gnelem() << "\">\n"; //out << "\t\t<CellData Scalars=\""<<scaname[0]<< "\" Vectors=\"" << vecname << "\">\n"; if(x.msize()>0 || y.msize()>0) { out << "\t\t<CellData "; if(x.msize() > 0) out << "Scalars=\"" << scaname[0] << "\" "; if(y.msize() > 0) out << "Vectors=\"" << vecname << "\""; out << ">\n"; } //enter cell scalar data if available if(x.msize() > 0) { //cout << "aoutput: Writing scalars..\n"; for(int in = 0; in < nscalars; in++) { out << "\t\t\t<DataArray type=\"Float64\" Name=\"" << scaname[in] << "\" Format=\"ascii\">\n"; for(int i = 0; i < m.gnelem(); i++) out << "\t\t\t\t" << x.get(i,in) << '\n'; out << "\t\t\t</DataArray>\n"; } //cout << "aoutput: Scalars written.\n"; } //enter vector cell data if available if(y.msize() > 0) { out << "\t\t\t<DataArray type=\"Float64\" Name=\"" << vecname << "\" NumberOfComponents=\"3\" Format=\"ascii\">\n"; for(int i = 0; i < m.gnelem(); i++) { out << "\t\t\t\t"; for(int idim = 0; idim < y.cols(); idim++) out << y.get(i,idim) << " "; if(y.cols() == 2) out << "0.0 "; out << '\n'; } out << "\t\t\t</DataArray>\n"; } if(x.msize() > 0 || y.msize() > 0) out << "\t\t</CellData>\n"; //enter points out << "\t\t<Points>\n"; out << "\t\t<DataArray type=\"Float64\" NumberOfComponents=\"3\" Format=\"ascii\">\n"; for(int i = 0; i < m.gnpoin(); i++) { out << "\t\t\t"; for(int idim = 0; idim < m.gndim(); idim++) out << m.gcoords(i,idim) << " "; if(m.gndim() == 2) out << "0.0 "; out << '\n'; } out << "\t\t</DataArray>\n"; out << "\t\t</Points>\n"; //enter cells out << "\t\t<Cells>\n"; out << "\t\t\t<DataArray type=\"UInt32\" Name=\"connectivity\" Format=\"ascii\">\n"; for(int i = 0; i < m.gnelem(); i++) { out << "\t\t\t\t"; for(int inode = 0; inode < m.gnnode(); inode++) out << m.ginpoel(i,inode) << " "; out << '\n'; } out << "\t\t\t</DataArray>\n"; out << "\t\t\t<DataArray type=\"UInt32\" Name=\"offsets\" Format=\"ascii\">\n"; for(int i = 0; i < m.gnelem(); i++) out << "\t\t\t\t" << m.gnnode()*(i+1) << '\n'; out << "\t\t\t</DataArray>\n"; out << "\t\t\t<DataArray type=\"Int32\" Name=\"types\" Format=\"ascii\">\n"; for(int i = 0; i < m.gnelem(); i++) out << "\t\t\t\t" << elemcode << '\n'; out << "\t\t\t</DataArray>\n"; out << "\t\t</Cells>\n"; //finish upper out << "\t</Piece>\n"; out << "</UnstructuredGrid>\n"; out << "</VTKFile>"; out.close(); std::cout << "Vtu file written.\n"; }