mesh.c
来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C语言 代码 · 共 478 行
C
478 行
#include "medit.h"#include "extern.h"#include "sproto.h"#define FLOAT_MAX 1.e20ubyte dosurf;double volTet(double *c1,double *c2,double *c3,double *c4) { double ax,ay,az,bx,by,bz,vol; ax = c3[0] - c1[0]; ay = c3[1] - c1[1]; az = c3[2] - c1[2]; bx = c4[0] - c1[0]; by = c4[1] - c1[1]; bz = c4[2] - c1[2]; vol = (c2[0]-c1[0]) * (ay*bz - az*by) \ + (c2[1]-c1[1]) * (az*bx - ax*bz) \ + (c2[2]-c1[2]) * (ax*by - ay*bx); return(vol / 6.0);}/* dump mesh info */void meshInfo(pMesh mesh) { fprintf(stdout," Vertices %8d",mesh->np); if ( mesh->nc ) fprintf(stdout," Corners %d",mesh->nc); if ( mesh->nr ) fprintf(stdout," Required %d",mesh->nr); fprintf(stdout,"\n"); if ( mesh->nt ) fprintf(stdout," Triangles %8d\n",mesh->nt); if ( mesh->nq ) fprintf(stdout," Quads %8d\n",mesh->nq); if ( mesh->ntet ) fprintf(stdout," Tetrahedra %8d\n",mesh->ntet); if ( mesh->nhex ) fprintf(stdout," Hexahedra %8d\n",mesh->nhex); if ( mesh->na ) { fprintf(stdout," Edges %8d",mesh->na); if ( mesh->nri ) fprintf(stdout," Ridges %d",mesh->nri); if ( mesh->nre ) fprintf(stdout," Required %d",mesh->nre); fprintf(stdout,"\n"); } if ( mesh->nvn || mesh->ntg) { fprintf(stdout," Normals %8d",mesh->nvn); fprintf(stdout," Tangents %d\n",mesh->ntg); } fprintf(stdout," Bounding box: x:[%g %g] y:[%g %g] z:[%g %g]\n", mesh->xmin,mesh->xmax,mesh->ymin,mesh->ymax,mesh->zmin,mesh->zmax);}void meshCoord(pMesh mesh,int displ) { pTetra pt1; pPoint ppt; pSolution ps; double *c1,*c2,*c3,*c4,mul,vold,volf; int k; /* default */ if ( ddebug ) printf("change mesh coord\n"); mul = 2.0*displ - 1.; if ( mesh->dim == 2 ) { for (k=1; k<=mesh->np; k++) { ppt = &mesh->point[k]; ps = &mesh->sol[k]; ppt->c[0] = ppt->c[0] + mul*ps->m[0]; ppt->c[1] = ppt->c[1] + mul*ps->m[1]; } } else { vold = 0.0; for (k=1; k<=mesh->ntet; k++) { pt1 = &mesh->tetra[k]; if ( !pt1->v[0] ) continue; c1 = &mesh->point[pt1->v[0]].c[0]; c2 = &mesh->point[pt1->v[1]].c[0]; c3 = &mesh->point[pt1->v[2]].c[0]; c4 = &mesh->point[pt1->v[3]].c[0]; vold += volTet(c1,c2,c3,c4); } for (k=1; k<=mesh->np; k++) { ppt = &mesh->point[k]; ps = &mesh->sol[k]; ppt->c[0] = mesh->xtra + ppt->c[0] + mul*ps->m[0]; ppt->c[1] = mesh->ytra + ppt->c[1] + mul*ps->m[1]; ppt->c[2] = mesh->ztra + ppt->c[2] + mul*ps->m[2]; } volf = 0.0; for (k=1; k<=mesh->ntet; k++) { pt1 = &mesh->tetra[k]; if ( !pt1->v[0] ) continue; c1 = &mesh->point[pt1->v[0]].c[0]; c2 = &mesh->point[pt1->v[1]].c[0]; c3 = &mesh->point[pt1->v[2]].c[0]; c4 = &mesh->point[pt1->v[3]].c[0]; volf += volTet(c1,c2,c3,c4); } fprintf(stdout," Volume: initial %E final %E\n",vold,volf); }}void meshBox(pMesh mesh,int bb) { pPoint ppt; int k; /* default */ if ( ddebug ) printf("compute mesh box\n"); if ( bb ) { mesh->xmin = mesh->ymin = mesh->zmin = FLOAT_MAX; mesh->xmax = mesh->ymax = mesh->zmax = -FLOAT_MAX; for (k=1; k<=mesh->np; k++) { ppt = &mesh->point[k]; if ( ppt->tag == M_UNUSED && mesh->ne ) continue; if ( ppt->c[0] < mesh->xmin ) mesh->xmin = ppt->c[0]; if ( ppt->c[0] > mesh->xmax ) mesh->xmax = ppt->c[0]; if ( ppt->c[1] < mesh->ymin ) mesh->ymin = ppt->c[1]; if ( ppt->c[1] > mesh->ymax ) mesh->ymax = ppt->c[1]; if ( ppt->c[2] < mesh->zmin ) mesh->zmin = ppt->c[2]; if ( ppt->c[2] > mesh->zmax ) mesh->zmax = ppt->c[2]; } } /* translate mesh at center */ mesh->xtra = 0.5 * (mesh->xmin+mesh->xmax); mesh->ytra = 0.5 * (mesh->ymin+mesh->ymax); mesh->ztra = 0.5 * (mesh->zmin+mesh->zmax); for (k=1; k<=mesh->np; k++) { ppt = &mesh->point[k]; /*if ( ppt->tag == M_UNUSED && mesh->ne ) continue;*/ ppt->c[0] -= mesh->xtra; ppt->c[1] -= mesh->ytra; ppt->c[2] -= mesh->ztra; }}int meshSurf(pMesh mesh) { pTetra ptt,pt2; pHexa ph; pTriangle pt; pQuad pq; int *adj,i,k,iadr; ubyte i1,i2,i3; static int idirt[7] = {0,1,2,3,0,1,2}; static int ch[6][4] = { {0,1,2,3}, {4,5,6,7}, {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {0,3,7,4} }; if ( !dosurf ) return(1); /* extract surface */ if ( mesh->ntet > 0 && !mesh->nt ) { if ( !hashTetra(mesh) ) return(0); for (k=1; k<=mesh->ntet; k++) { ptt = &mesh->tetra[k]; if ( !ptt->v[0] ) continue; iadr = 4*(k-1)+1; adj = &mesh->adja[iadr]; for (i=0; i<4; i++) if ( !adj[i] ) ++mesh->nt; else { pt2 = &mesh->tetra[adj[i]]; if ( ptt->ref != pt2->ref && k < adj[i] ) ++mesh->nt; } } /* memory alloc */ if ( ddebug ) printf("allocate %d tria\n",mesh->nt); mesh->tria = (pTriangle)calloc(mesh->nt+1,sizeof(struct striangle)); if ( !mesh->tria ) { fprintf(stdout," ## No triangle\n"); return(0); } /* find triangles */ mesh->nt = 0; for (k=1; k<=mesh->ntet; k++) { ptt = &mesh->tetra[k]; if ( !ptt->v[0] ) continue; iadr = 4*(k-1)+1; adj = &mesh->adja[iadr]; for (i=0; i<4; i++) { if ( !adj[i] ) { pt = &mesh->tria[++mesh->nt]; i1 = idirt[i+1]; i2 = idirt[i+2]; i3 = idirt[i+3]; pt->v[0] = ptt->v[i1]; pt->v[1] = ptt->v[i2]; pt->v[2] = ptt->v[i3]; pt->ref = 0; } else { pt2 = &mesh->tetra[adj[i]]; if ( (ptt->ref != pt2->ref) && (k < adj[i]) ) { pt = &mesh->tria[++mesh->nt]; i1 = idirt[i+1]; i2 = idirt[i+2]; i3 = idirt[i+3]; pt->v[0] = ptt->v[i1]; pt->v[1] = ptt->v[i2]; pt->v[2] = ptt->v[i3]; pt->ref = max(ptt->ref,pt2->ref); } } } } } if ( mesh->nhex > 0 && !mesh->nq ) { if ( mesh->adja ) { free(mesh->adja); free(mesh->voy); mesh->adja = 0; mesh->voy = 0; } if ( !hashHexa(mesh) ) return(0); for (k=1; k<=mesh->nhex; k++) { ph = &mesh->hexa[k]; if ( !ph->v[0] ) continue; iadr = 6*(k-1)+1; adj = &mesh->adja[iadr]; for (i=0; i<6; i++) if ( !adj[i] ) ++mesh->nq; } /* memory alloc */ if ( ddebug ) printf("allocate %d quads\n",mesh->nq); mesh->quad = (pQuad)calloc(mesh->nq+1,sizeof(struct squad)); if ( !mesh->quad ) { fprintf(stdout," ## No quad\n"); return(0); } /* find quadrilaterals */ mesh->nq = 0; for (k=1; k<=mesh->nhex; k++) { ph = &mesh->hexa[k]; if ( !ph->v[0] ) continue; iadr = 6*(k-1)+1; adj = &mesh->adja[iadr]; for (i=0; i<6; i++) if ( !adj[i] ) { pq = &mesh->quad[++mesh->nq]; pq->v[0] = ph->v[ch[i][0]]; pq->v[1] = ph->v[ch[i][1]]; pq->v[2] = ph->v[ch[i][2]]; pq->v[3] = ph->v[ch[i][3]]; } } } return(1);}void meshRef(pScene sc,pMesh mesh) { pMaterial pm; pTriangle pt; pQuad pq; pTetra pte; pHexa ph; pPoint ppt; int *old,i,k,m,nmat; /* default */ if ( ddebug ) printf(" assign %d references\n",sc->par.nbmat-1); /* sort elements by references */ if ( !quiet ) fprintf(stdout," Identifying sub-domains\n"); old = (int*)calloc(sc->par.nbmat+1,sizeof(int)); if ( !old ) exit(2); for (m=0; m<sc->par.nbmat; m++) { pm = &sc->material[m]; pm->ext[0] = mesh->xmax-mesh->xtra; pm->ext[1] = mesh->ymax-mesh->ytra; pm->ext[2] = mesh->zmax-mesh->ztra; pm->ext[3] = mesh->xmin-mesh->xtra; pm->ext[4] = mesh->ymin-mesh->ytra; pm->ext[5] = mesh->zmin-mesh->ztra; } for (k=mesh->nt; k>0; k--) { pt = &mesh->tria[k]; if ( !pt->v[0] ) continue; nmat = matRef(sc,pt->ref); /*nmat = !pt->ref ? DEFAULT_MAT : 1+(pt->ref-1)%(sc->par.nbmat-1);*/ pt->nxt = old[nmat]; old[nmat] = k; pm = &sc->material[nmat]; for (i=0; i<3; i++) { ppt = &mesh->point[pt->v[i]]; pm->ext[0] = min(pm->ext[0],ppt->c[0]); pm->ext[1] = min(pm->ext[1],ppt->c[1]); pm->ext[2] = min(pm->ext[2],ppt->c[2]); pm->ext[3] = max(pm->ext[3],ppt->c[0]); pm->ext[4] = max(pm->ext[4],ppt->c[1]); pm->ext[5] = max(pm->ext[5],ppt->c[2]); } } for (m=0;m<sc->par.nbmat; m++) { pm = &sc->material[m]; pm->depmat[LTria] = old[m]; old[m] = 0; } for (k=mesh->nq; k>0; k--) { pq = &mesh->quad[k]; if ( !pq->v[0] ) continue; nmat = matRef(sc,pq->ref); /*nmat = !pq->ref ? DEFAULT_MAT : 1+(pq->ref-1)%(sc->par.nbmat-1);*/ pq->nxt = old[nmat]; old[nmat] = k; pm = &sc->material[nmat]; for (i=0; i<4; i++) { ppt = &mesh->point[pq->v[i]]; pm->ext[0] = min(pm->ext[0],ppt->c[0]); pm->ext[1] = min(pm->ext[1],ppt->c[1]); pm->ext[2] = min(pm->ext[2],ppt->c[2]); pm->ext[3] = max(pm->ext[3],ppt->c[0]); pm->ext[4] = max(pm->ext[4],ppt->c[1]); pm->ext[5] = max(pm->ext[5],ppt->c[2]); } } for (m=0;m<sc->par.nbmat; m++) { pm = &sc->material[m]; pm->depmat[LQuad] = old[m]; old[m] = 0; } for (k=mesh->ntet; k>0; k--) { pte = &mesh->tetra[k]; if ( !pte->v[0] ) continue; nmat = matRef(sc,pte->ref); /*nmat = !pte->ref ? DEFAULT_MAT : 1+(pte->ref-1)%(sc->par.nbmat-1);*/ pte->nxt = old[nmat]; old[nmat] = k; pm = &sc->material[nmat]; for (i=0; i<4; i++) { ppt = &mesh->point[pte->v[i]]; pm->ext[0] = min(pm->ext[0],ppt->c[0]); pm->ext[1] = min(pm->ext[1],ppt->c[1]); pm->ext[2] = min(pm->ext[2],ppt->c[2]); pm->ext[3] = max(pm->ext[3],ppt->c[0]); pm->ext[4] = max(pm->ext[4],ppt->c[1]); pm->ext[5] = max(pm->ext[5],ppt->c[2]); } } for (m=0;m<sc->par.nbmat; m++) { pm = &sc->material[m]; pm->depmat[LTets] = old[m]; old[m] = 0; } for (k=mesh->nhex; k>0; k--) { ph = &mesh->hexa[k]; nmat = matRef(sc,ph->ref); /*nmat = !ph->ref ? DEFAULT_MAT : 1+(ph->ref-1)%(sc->par.nbmat-1);*/ ph->nxt = old[nmat]; old[nmat] = k; pm = &sc->material[nmat]; for (i=0; i<8; i++) { ppt = &mesh->point[ph->v[i]]; pm->ext[0] = min(pm->ext[0],ppt->c[0]); pm->ext[1] = min(pm->ext[1],ppt->c[1]); pm->ext[2] = min(pm->ext[2],ppt->c[2]); pm->ext[3] = max(pm->ext[3],ppt->c[0]); pm->ext[4] = max(pm->ext[4],ppt->c[1]); pm->ext[5] = max(pm->ext[5],ppt->c[2]); } } for (m=0;m<sc->par.nbmat; m++) { pm = &sc->material[m]; pm->depmat[LHexa] = old[m]; old[m] = 0; } free(old); /* remove unused materials *//* for (m=1; m<sc->par.nbmat; m++) { pm = &sc->material[m]; if ( !pm->depmat[LTria] && !pm->depmat[LQuad] && !pm->depmat[LTets] && !pm->depmat[LHexa] ) { pm1 = &sc->material[sc->par.nbmat-1]; memcpy(pm,pm1,sizeof(struct material)); sc->par.nbmat--; m--; } }*/ if ( ddebug ) for (m=0; m<sc->par.nbmat; m++) { pm = &sc->material[m]; if ( pm->depmat[LTria] || pm->depmat[LQuad] || pm->depmat[LTets] || pm->depmat[LHexa] ) fprintf(stdout," depart[%d], ref %d = %d %d %d %d\n", m,pm->ref,pm->depmat[LTria],pm->depmat[LQuad], pm->depmat[LTets],pm->depmat[LHexa]); }}int meshUpdate(pScene sc,pMesh mesh) { int k,ret; clock_t ct; /* release mesh structure */ if ( ddebug ) fprintf(stdout,"loadMesh: update mesh\n"); if ( mesh->tria ) { M_free(mesh->tria); mesh->tria = 0; } if ( mesh->quad ) { M_free(mesh->quad); mesh->quad = 0; } if ( mesh->edge ) { M_free(mesh->edge); mesh->edge = 0; } if ( mesh->tetra ) { M_free(mesh->tetra); mesh->tetra = 0; } if ( mesh->hexa ) { M_free(mesh->hexa); mesh->hexa = 0; } if ( mesh->adja ) { M_free(mesh->adja); mesh->adja = 0; } if ( mesh->voy ) { M_free(mesh->voy); mesh->voy = 0; } if ( mesh->point ) { M_free(mesh->point); mesh->point = 0; } if ( mesh->extra ) { if ( mesh->extra->iv ) M_free(mesh->extra->nv); if ( mesh->extra->it ) M_free(mesh->extra->nt); if ( mesh->extra->iq ) M_free(mesh->extra->nq); if ( mesh->extra->n ) M_free(mesh->extra->n); M_free(mesh->extra); mesh->extra = 0; } if ( mesh->nbb && mesh->sol ) { if ( (mesh->dim==2 && mesh->nfield==3) || (mesh->dim==3 && mesh->nfield==6) ) for (k=1; k<=mesh->nbb; k++) free(mesh->sol[k].m); M_free(mesh->sol); mesh->sol = 0; } /* read mesh */ fprintf(stdout," Loading data file(s)\n"); ct = clock(); ret = 0; switch ( mesh->typ ) { case 0: ret = loadMesh(mesh); break; case 1: ret = inmsh2(mesh); break; case 2: ret = loadGIS(mesh); break; } if ( !ret ) return(0); /* compute mesh box */ if ( (mesh->ntet && !mesh->nt) || (mesh->nhex && !mesh->nq) ) meshSurf(mesh); meshBox(mesh,1); /*parsop(sc,mesh);*/ if ( !quiet ) meshInfo(mesh); /* read metric */ if ( !loadSol(mesh,mesh->name,1) ) bbfile(mesh); if ( !quiet && mesh->nbb ) fprintf(stdout," Solutions %8d\n",mesh->nbb); ct = difftime(clock(),ct); fprintf(stdout," Input seconds: %.2f\n", (double)ct/(double)CLOCKS_PER_SEC); return(1);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?