📄 get_cells.c
字号:
#define RCSID "$Id: Get_Cells.c,v 1.12 2006/02/26 00:42:54 geuzaine Exp $"/* * Copyright (C) 1997-2006 P. Dular, C. Geuzaine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * * Please report all bugs and problems to <getdp@geuz.org>. */#include "GetDP.h"#include "Get_Geometry.h"#include "Get_Cells.h"#include "GeoData.h"#include "CurrentData.h"#include "Numeric.h"void Get_BarycentricDivision(struct Element * Element, double Bary_Edge[][3], double Bary_Facet[][3], double Bary_Volume[3]){ int i, j, *IM, *NumNodes, *NumEdges, Nbr_Edges, Nbr_Facets ; GetDP_Begin("Get_BarycentricDivision"); i = 0; IM = Geo_GetIM_Den(Element->GeoElement->Type, &Nbr_Edges) ; do{ NumNodes = IM + i * NBR_MAX_SUBENTITIES_IN_ELEMENT ; Bary_Edge[i][0] = (Element->x[abs(NumNodes[0])-1]+Element->x[abs(NumNodes[1])-1])/2. ; Bary_Edge[i][1] = (Element->y[abs(NumNodes[0])-1]+Element->y[abs(NumNodes[1])-1])/2. ; Bary_Edge[i][2] = (Element->z[abs(NumNodes[0])-1]+Element->z[abs(NumNodes[1])-1])/2. ; i++ ; } while (i<Nbr_Edges) ; if(Nbr_Edges > 1){ i = 0; IM = Geo_GetIM_Dfe(Element->GeoElement->Type, &Nbr_Facets) ; do{ NumEdges = IM + i * NBR_MAX_SUBENTITIES_IN_ELEMENT ; Bary_Facet[i][0] = Bary_Facet[i][1] = Bary_Facet[i][2] = 0. ; j = 0; while(NumEdges[j]!=0){ Bary_Facet[i][0] += Bary_Edge[abs(NumEdges[j])-1][0] ; Bary_Facet[i][1] += Bary_Edge[abs(NumEdges[j])-1][1] ; Bary_Facet[i][2] += Bary_Edge[abs(NumEdges[j])-1][2] ; j++ ; } Bary_Facet[i][0] /= (double)j; Bary_Facet[i][1] /= (double)j; Bary_Facet[i][2] /= (double)j; i++ ; } while (i<Nbr_Facets) ; if(Nbr_Facets > 1){ Bary_Volume[0] = Bary_Volume[1] = Bary_Volume[2] = 0. ; for(i=0 ; i<Nbr_Facets ; i++){ Bary_Volume[0] += Bary_Facet[i][0] ; Bary_Volume[1] += Bary_Facet[i][1] ; Bary_Volume[2] += Bary_Facet[i][2] ; } Bary_Volume[0] /= (double)Nbr_Facets; Bary_Volume[1] /= (double)Nbr_Facets; Bary_Volume[2] /= (double)Nbr_Facets; } } GetDP_End ;}static struct Geo_Element deRhamGeoElement[20] ;void Get_deRhamCells(struct Element *Element, struct QuantityStorage *QuantityStorage, struct Group * Group, int *Nbr_Cells, struct Element Cells[], struct Value Vec[], int *Relative_Jacobian){ double Bary_Edge[12][3], Bary_Facet[6][3], Bary_Volume[3], *uvw, norm ; int i ; GetDP_Begin("Get_deRhamCells"); *Nbr_Cells = QuantityStorage->NbrElementaryBasisFunction ; for(i=0 ; i<*Nbr_Cells ; i++) { Cells[i].GeoElement = &deRhamGeoElement[i] ; Cells[i].GeoElement->Num = -1 ; Cells[i].GeoElement->Region = Cells[i].Region = Element->Region ; Cells[i].GeoElement->NumNodes = NULL ; } switch (Group->FunctionType) { /* ------------------------------------------------------------ */ /* Primal mesh cells */ /* ------------------------------------------------------------ */ case NODESOF : *Relative_Jacobian = -3 ; /* dummy */ uvw = Geo_GetNodes_uvw(Element->Type, &i) ; for(i = 0 ; i < *Nbr_Cells ; i++){ Cells[i].GeoElement->Type = Cells[i].Type = POINT ; Cells[i].GeoElement->NbrNodes = 1 ; /* This a a hack: x,y,z <- u,v,w */ Cells[i].x[0] = uvw[3 * QuantityStorage->BasisFunction[i].NumEntityInElement ] ; Cells[i].y[0] = uvw[3 * QuantityStorage->BasisFunction[i].NumEntityInElement + 1] ; Cells[i].z[0] = uvw[3 * QuantityStorage->BasisFunction[i].NumEntityInElement + 2] ; } break ; case EDGESOF : Msg(GERROR, "de Rham Map on EdgesOf not Done") ; break; case FACETSOF : Msg(GERROR, "de Rham Map on FacetsOf not Done") ; break; case VOLUMESOF : *Relative_Jacobian = 0 ; if(*Nbr_Cells > 1) Msg(GERROR, "Non consistent choice of VolumesOf"); Cells[0] = *Element ; break; /* ------------------------------------------------------------ */ /* Dual mesh cells */ /* ------------------------------------------------------------ */ case DUALNODESOF : *Relative_Jacobian = 0 ; Get_BarycentricDivision(Element, Bary_Edge, Bary_Facet, Bary_Volume) ; switch(Element->Type){ case LINE : for(i = 0 ; i < *Nbr_Cells ; i++){ Cells[i].GeoElement->Type = Cells[i].Type = LINE ; Cells[i].GeoElement->NbrNodes = 2 ; switch(QuantityStorage->BasisFunction[i].NumEntityInElement){ case 0 : Cells[i].x[0] = Element->x[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].y[0] = Element->y[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].z[0] = Element->z[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].x[1] = Bary_Edge[0][0] ; Cells[i].y[1] = Bary_Edge[0][1] ; Cells[i].z[1] = Bary_Edge[0][2] ; break ; case 1 : Cells[i].x[0] = Bary_Edge[0][0] ; Cells[i].y[0] = Bary_Edge[0][1] ; Cells[i].z[0] = Bary_Edge[0][2] ; Cells[i].x[1] = Element->x[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].y[1] = Element->y[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].z[1] = Element->z[QuantityStorage->BasisFunction[i].NumEntityInElement] ; break ; } } break; case TRIANGLE : for(i = 0 ; i < *Nbr_Cells ; i++){ Cells[i].GeoElement->Type = Cells[i].Type = QUADRANGLE ; Cells[i].GeoElement->NbrNodes = 4 ; Cells[i].x[0] = Element->x[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].y[0] = Element->y[QuantityStorage->BasisFunction[i].NumEntityInElement] ; Cells[i].z[0] = Element->z[QuantityStorage->BasisFunction[i].NumEntityInElement]; Cells[i].x[2] = Bary_Facet[0][0] ; Cells[i].y[2] = Bary_Facet[0][1] ; Cells[i].z[2] = Bary_Facet[0][2] ; switch(QuantityStorage->BasisFunction[i].NumEntityInElement){ case 0 : Cells[i].x[1] = Bary_Edge[0][0] ; Cells[i].x[3] = Bary_Edge[1][0] ; Cells[i].y[1] = Bary_Edge[0][1] ; Cells[i].y[3] = Bary_Edge[1][1] ; Cells[i].z[1] = Bary_Edge[0][2] ; Cells[i].z[3] = Bary_Edge[1][2] ; break ; case 1 : Cells[i].x[1] = Bary_Edge[2][0] ; Cells[i].x[3] = Bary_Edge[0][0] ; Cells[i].y[1] = Bary_Edge[2][1] ; Cells[i].y[3] = Bary_Edge[0][1] ; Cells[i].z[1] = Bary_Edge[2][2] ; Cells[i].z[3] = Bary_Edge[0][2] ; break ; case 2 : Cells[i].x[1] = Bary_Edge[1][0] ; Cells[i].x[3] = Bary_Edge[2][0] ; Cells[i].y[1] = Bary_Edge[1][1] ; Cells[i].y[3] = Bary_Edge[2][1] ; Cells[i].z[1] = Bary_Edge[1][2] ; Cells[i].z[3] = Bary_Edge[2][2] ; break ; } } break; default : Msg(GERROR, "Unknown Element type for DualNodesOf"); break; } break; case DUALEDGESOF : *Relative_Jacobian = -1 ; Get_BarycentricDivision(Element, Bary_Edge, Bary_Facet, Bary_Volume) ; switch(Element->Type){ case TRIANGLE : for(i=0 ; i<*Nbr_Cells ; i++){ Cells[i].GeoElement->Type = Cells[i].Type = LINE ; Cells[i].GeoElement->NbrNodes = 2 ; Cells[i].x[0] = Bary_Edge[QuantityStorage->BasisFunction[i].NumEntityInElement][0] ; Cells[i].y[0] = Bary_Edge[QuantityStorage->BasisFunction[i].NumEntityInElement][1] ; Cells[i].z[0] = Bary_Edge[QuantityStorage->BasisFunction[i].NumEntityInElement][2] ; Cells[i].x[1] = Bary_Facet[0][0] ; Cells[i].y[1] = Bary_Facet[0][1] ; Cells[i].z[1] = Bary_Facet[0][2] ; Vec[i].Type = VECTOR ; /* tangent */ Vec[i].Val[0] = Cells[i].x[1] - Cells[i].x[0] ; Vec[i].Val[1] = Cells[i].y[1] - Cells[i].y[0] ; Vec[i].Val[2] = Cells[i].z[1] - Cells[i].z[0] ; norm = sqrt(DSQU(Vec[i].Val[0])+DSQU(Vec[i].Val[1])+DSQU(Vec[i].Val[2])); Vec[i].Val[0] /= norm ; Vec[i].Val[1] /= norm ; Vec[i].Val[2] /= norm ; if(i==1){ Vec[i].Val[0] *= -1 ; Vec[i].Val[1] *= -1 ; Vec[i].Val[2] *= -1 ; } } break; default : Msg(GERROR, "Unknown Element type for DualEdgesOf"); break; } break; case DUALFACETSOF : case DUALVOLUMESOF : Msg(GERROR, "de Rham Map on DualFacetsOf and DualVolumesOf not done") ; break ; /* ------------------------------------------------------------ */ /* Boundary of dual mesh cells */ /* ------------------------------------------------------------ */ case BOUNDARYOFDUALNODESOF : *Relative_Jacobian = -1 ; Get_BarycentricDivision(Element, Bary_Edge, Bary_Facet, Bary_Volume) ; switch(Element->Type){ case LINE : for(i=0 ; i<2 ; i++){ Cells[i].GeoElement->Type = Cells[i].Type = POINT ; Cells[i].GeoElement->NbrNodes = 1 ; /* This a a hack: x,y,z <- u,v,w */ Cells[i].x[0] = 0. ; Cells[i].y[0] = 0. ; Cells[i].z[0] = 0. ; } break; case TRIANGLE : for(i=0 ; i<3 ; i++){ Cells[i].GeoElement->Type = Cells[i].Type = LINE ; Cells[i].GeoElement->NbrNodes = 2 ; Cells[i].x[0] = Bary_Edge[i][0] ; Cells[i].y[0] = Bary_Edge[i][1] ; Cells[i].z[0] = Bary_Edge[i][2] ; Cells[i].x[1] = Bary_Facet[0][0] ; Cells[i].y[1] = Bary_Facet[0][1] ; Cells[i].z[1] = Bary_Facet[0][2] ; Vec[i].Type = VECTOR ; /* normal. Only valid for 2D cases ! */ Vec[i].Val[0] = Cells[i].y[1] - Cells[i].y[0] ; Vec[i].Val[1] = Cells[i].x[0] - Cells[i].x[1] ; Vec[i].Val[2] = 0; norm = sqrt(DSQU(Vec[i].Val[0])+DSQU(Vec[i].Val[1])+DSQU(Vec[i].Val[2])); Vec[i].Val[0] /= norm ; Vec[i].Val[1] /= norm ; Vec[i].Val[2] /= norm ; if(i==1){ Vec[i].Val[0] *= -1 ; Vec[i].Val[1] *= -1 ; Vec[i].Val[2] *= -1 ; } } break; default : Msg(GERROR, "Unknown Element type for BoundaryOfDualNodesOf"); break; } break; case BOUNDARYOFDUALEDGESOF : Msg(GERROR, "de Rham Map on BoundaryOfDualEdgesOf not done") ; break; default: Msg(GERROR, "Unknown type of Entity in de Rham Map"); break; } GetDP_End ;}static struct Geo_Element IntegrationGeoElement[20] ;void Get_IntegrationCells(struct Element *Element, double x, double y, double z, int *Nbr_Cells, struct Element Cells[]) { int i, j ; GetDP_Begin("Get_IntegrationCells"); switch(Element->Type){ case TRIANGLE : *Nbr_Cells = 3 ; for(i = 0 ; i < *Nbr_Cells ; i++){ Cells[i].GeoElement = &IntegrationGeoElement[i] ; Cells[i].GeoElement->Num = -1 ; Cells[i].GeoElement->Type = Cells[i].Type = TRIANGLE ; Cells[i].GeoElement->Region = Cells[i].Region = Element->Region ; Cells[i].GeoElement->NbrNodes = 3 ; Cells[i].GeoElement->NumNodes = NULL ; Cells[i].x[0] = x ; Cells[i].y[0] = y ; Cells[i].z[0] = z ; Cells[i].x[1] = Element->x[i] ; Cells[i].y[1] = Element->y[i] ; Cells[i].z[1] = Element->z[i] ; j = (i<2)?i+1:0 ; Cells[i].x[2] = Element->x[j] ; Cells[i].y[2] = Element->y[j] ; Cells[i].z[2] = Element->z[j] ; } break; default : Msg(GERROR, "Unknown Element type for Get_IntegrationCells"); break; } GetDP_End ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -