Commit eec68ea7 authored by Jonathan Lambrechts's avatar Jonathan Lambrechts
Browse files

introduce FEElement and FEFields

parent b40fadaa
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
set(SRC set(SRC
fluid_problem.c fluid_problem.c
fluid_problem_concentration.c fluid_problem_concentration.c
fluid_problem_fem.c
mesh.c mesh.c
mesh_find.c mesh_find.c
../tools/quadtree.c ../tools/quadtree.c
......
This diff is collapsed.
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "mesh.h" #include "mesh.h"
#include "mesh_find.h" #include "mesh_find.h"
#include "fluid_problem_fem.h"
#if DIMENSION==2 #if DIMENSION==2
#define N_N 3 #define N_N 3
...@@ -35,7 +36,6 @@ ...@@ -35,7 +36,6 @@
typedef void BoundaryCallback(int n, const double *x, double *bnd); typedef void BoundaryCallback(int n, const double *x, double *bnd);
typedef struct { typedef struct {
char *tag; char *tag;
int row; int row;
...@@ -101,6 +101,7 @@ struct FluidProblem { ...@@ -101,6 +101,7 @@ struct FluidProblem {
int advection; int advection;
int temporal; int temporal;
int drag_in_stab; int drag_in_stab;
FEFields *fields, *field_porosity, *field_concentration;
}; };
// complete force on the particle (including gravity) // complete force on the particle (including gravity)
...@@ -144,7 +145,7 @@ void fluid_problem_set_stab_param(FluidProblem *p, double stab_param); ...@@ -144,7 +145,7 @@ void fluid_problem_set_stab_param(FluidProblem *p, double stab_param);
void fluid_problem_set_reduced_gravity(FluidProblem *p, int reduced_gravity); void fluid_problem_set_reduced_gravity(FluidProblem *p, int reduced_gravity);
int weak_boundary_n_values(const WeakBoundary *wbnd); int weak_boundary_n_values(const WeakBoundary *wbnd);
void weak_boundary_values(const FEFields *fields, const Mesh *mesh, const MeshBoundary *bnd, const WeakBoundary *wbnd, double *data);
double fluid_problem_a_integ_volume(FluidProblem *problem); double fluid_problem_a_integ_volume(FluidProblem *problem);
double fluid_problem_a_integ_bnd(FluidProblem *problem, double dt); double fluid_problem_a_integ_bnd(FluidProblem *problem, double dt);
void weak_boundary_values(const Mesh *mesh, const MeshBoundary *bnd, const WeakBoundary *wbnd, double *data);
#endif #endif
...@@ -19,6 +19,8 @@ int mesh_boundary_id_from_tag(const Mesh *mesh, const char *tag) { ...@@ -19,6 +19,8 @@ int mesh_boundary_id_from_tag(const Mesh *mesh, const char *tag) {
} }
void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
#if 0
const FEElement *element = problem->fields->element[0];
const Mesh *mesh = problem->mesh; const Mesh *mesh = problem->mesh;
const int n_fields = fluid_problem_n_fields(problem); const int n_fields = fluid_problem_n_fields(problem);
double *velocity = malloc(D*problem->mesh->n_nodes*sizeof(double)); double *velocity = malloc(D*problem->mesh->n_nodes*sizeof(double));
...@@ -40,10 +42,10 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -40,10 +42,10 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
dxdxi[i][j] = mesh->x[el[j+1]*3+i] - mesh->x[el[0]*3+i]; dxdxi[i][j] = mesh->x[el[j+1]*3+i] - mesh->x[el[0]*3+i];
const double detj = invDD(dxdxi, dxidx); const double detj = invDD(dxdxi, dxidx);
det[iel] = detj; det[iel] = detj;
grad_shape_functions(dxidx, dphi); element->df(QP[0], dxidx, dphi);
double da[D] = {0}; double da[D] = {0};
double divu = 0; double divu = 0;
for (int i = 0; i < N_SF; ++i) { for (int i = 0; i < element->nlocal; ++i) {
for (int id = 0; id < D; ++id) { for (int id = 0; id < D; ++id) {
da[id] += dphi[i][id]*problem->concentration[iel*N_N+i]; da[id] += dphi[i][id]*problem->concentration[iel*N_N+i];
divu += dphi[i][id]*problem->solution[el[i]*n_fields+id]; divu += dphi[i][id]*problem->solution[el[i]*n_fields+id];
...@@ -51,13 +53,13 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -51,13 +53,13 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
} }
for (int iqp = 0; iqp< N_QP; ++iqp) { for (int iqp = 0; iqp< N_QP; ++iqp) {
double phi[N_SF]; double phi[element->nlocal];
shape_functions(QP[iqp],phi); element->f(QP[iqp],phi);
double u[D] = {0}; double u[D] = {0};
double c = 0; double c = 0;
double cold = 0; double cold = 0;
double a = 0; double a = 0;
for (int i = 0; i < N_SF; ++i) { for (int i = 0; i < element->nlocal; ++i) {
a += phi[i]*problem->concentration[iel*N_N+i]; a += phi[i]*problem->concentration[iel*N_N+i];
c += phi[i]*problem->porosity[el[i]]; c += phi[i]*problem->porosity[el[i]];
cold += phi[i]*problem->oldporosity[el[i]]; cold += phi[i]*problem->oldporosity[el[i]];
...@@ -70,7 +72,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -70,7 +72,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
r -= u[id]*da[id]; r -= u[id]*da[id];
} }
const double jw = QW[iqp]*detj; const double jw = QW[iqp]*detj;
for (int i = 0; i < N_SF; ++i) { for (int i = 0; i < element->nlocal; ++i) {
rhs[iel*N_N+i] += r*phi[i]*jw; rhs[iel*N_N+i] += r*phi[i]*jw;
} }
} }
...@@ -81,12 +83,12 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -81,12 +83,12 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
const int iel0 = interface[0]; const int iel0 = interface[0];
const int iel1 = interface[2]; const int iel1 = interface[2];
if (iel1 < 0) continue; if (iel1 < 0) continue;
const int *cl0 = elbnd[interface[1]]; const int *cl0 = element->boundaries[interface[1]];
const int *cl1 = elbnd[interface[3]]; const int *cl1 = element->boundaries[interface[3]];
double *x[N_LSF]; double *x[element->boundary_element->nlocal];
const int *el0 = &mesh->elements[iel0*N_N]; const int *el0 = &mesh->elements[iel0*N_N];
const int *el1 = &mesh->elements[iel1*N_N]; const int *el1 = &mesh->elements[iel1*N_N];
for (int i = 0; i < N_LSF; ++i){ for (int i = 0; i < element->boundary_element->nlocal; ++i){
x[i] = &mesh->x[el0[cl0[i]]*3]; x[i] = &mesh->x[el0[cl0[i]]*3];
} }
double detbnd, n[D]; double detbnd, n[D];
...@@ -94,9 +96,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -94,9 +96,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iqp = 0; iqp < N_LQP; ++iqp) { for (int iqp = 0; iqp < N_LQP; ++iqp) {
double a0 = 0, a1 = 0, un = 0; double a0 = 0, a1 = 0, un = 0;
double phil[N_LQP]; double phil[N_LQP];
l_shape_functions(LQP[iqp],phil); element->boundary_element->f(LQP[iqp],phil);
double c = 0; double c = 0;
for (int i = 0; i < N_LSF; ++i) { for (int i = 0; i < element->boundary_element->nlocal; ++i) {
a0 += problem->concentration[iel0*N_N+cl0[i]]*phil[i]; a0 += problem->concentration[iel0*N_N+cl0[i]]*phil[i];
a1 += problem->concentration[iel1*N_N+cl1[i]]*phil[i]; a1 += problem->concentration[iel1*N_N+cl1[i]]*phil[i];
c += problem->porosity[el0[cl0[i]]]*phil[i]; c += problem->porosity[el0[cl0[i]]]*phil[i];
...@@ -108,7 +110,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -108,7 +110,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
const double r0 = -un*(a-a0); const double r0 = -un*(a-a0);
const double r1 = un*(a-a1); const double r1 = un*(a-a1);
const double jw = LQW[iqp]*detbnd; const double jw = LQW[iqp]*detbnd;
for (int i = 0; i < N_LSF; ++i){ for (int i = 0; i < element->boundary_element->nlocal; ++i){
rhs[iel0*N_N+cl0[i]] += phil[i]*r0*jw; rhs[iel0*N_N+cl0[i]] += phil[i]*r0*jw;
rhs[iel1*N_N+cl1[i]] += phil[i]*r1*jw; rhs[iel1*N_N+cl1[i]] += phil[i]*r1*jw;
} }
...@@ -121,7 +123,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -121,7 +123,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
if (wbnd->type == BND_WALL) continue; if (wbnd->type == BND_WALL) continue;
int n_value = weak_boundary_n_values(wbnd); int n_value = weak_boundary_n_values(wbnd);
double *data = malloc(N_LQP*n_value*bnd->n_interfaces*sizeof(double)); double *data = malloc(N_LQP*n_value*bnd->n_interfaces*sizeof(double));
weak_boundary_values(mesh, bnd, wbnd, data); weak_boundary_values(problem->fields, mesh, bnd, wbnd, data);
if (wbnd->aid<0){ if (wbnd->aid<0){
printf("concentration should be specified on open boundary %s.",wbnd->tag); printf("concentration should be specified on open boundary %s.",wbnd->tag);
exit(1); exit(1);
...@@ -129,9 +131,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -129,9 +131,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iinterface = 0; iinterface < bnd->n_interfaces; ++iinterface) { for (int iinterface = 0; iinterface < bnd->n_interfaces; ++iinterface) {
const int *interface = &mesh->interfaces[bnd->interfaces[iinterface]*4]; const int *interface = &mesh->interfaces[bnd->interfaces[iinterface]*4];
const int iel = interface[0]; const int iel = interface[0];
const int *cl = elbnd[interface[1]]; const int *cl = element->boundaries[interface[1]];
const int *el = &mesh->elements[iel*N_N]; const int *el = &mesh->elements[iel*N_N];
double *x[N_LSF]; double *x[element->boundary_element->nlocal];
for (int i = 0; i < D; ++i){ for (int i = 0; i < D; ++i){
x[i] = &mesh->x[el[cl[i]]*3]; x[i] = &mesh->x[el[cl[i]]*3];
} }
...@@ -140,10 +142,10 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -140,10 +142,10 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iqp = 0; iqp < N_LQP; ++iqp) { for (int iqp = 0; iqp < N_LQP; ++iqp) {
const double *dataqp = &data[n_value*(iinterface*N_LQP+iqp)]; const double *dataqp = &data[n_value*(iinterface*N_LQP+iqp)];
double phil[N_LQP]; double phil[N_LQP];
l_shape_functions(LQP[iqp],phil); element->boundary_element->f(LQP[iqp],phil);
double a = 0; double a = 0;
double c = 0; double c = 0;
for (int i = 0; i < N_LSF; ++i) { for (int i = 0; i < element->boundary_element->nlocal; ++i) {
a += problem->concentration[iel*N_N+cl[i]]*phil[i]; a += problem->concentration[iel*N_N+cl[i]]*phil[i];
c += problem->porosity[el[cl[i]]]*phil[i]; c += problem->porosity[el[cl[i]]]*phil[i];
} }
...@@ -153,14 +155,14 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -153,14 +155,14 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
un += n[id]*dataqp[wbnd->vid+id]; un += n[id]*dataqp[wbnd->vid+id];
} }
else { else {
for (int i = 0; i < N_LSF; ++i) { for (int i = 0; i < element->boundary_element->nlocal; ++i) {
un += phil[i]*problem->solution[el[cl[i]]*n_fields+id]*n[id]; un += phil[i]*problem->solution[el[cl[i]]*n_fields+id]*n[id];
} }
} }
} }
const double jw = LQW[iqp]*detbnd; const double jw = LQW[iqp]*detbnd;
double f0 = -un * (un > 0 ? 0 : dataqp[wbnd->aid]-a); double f0 = -un * (un > 0 ? 0 : dataqp[wbnd->aid]-a);
for (int iphi = 0; iphi < N_LSF; ++iphi){ for (int iphi = 0; iphi < element->boundary_element->nlocal; ++iphi){
rhs[iel*N_N+cl[iphi]] += phil[iphi]*f0*jw; rhs[iel*N_N+cl[iphi]] += phil[iphi]*f0*jw;
} }
} }
...@@ -173,9 +175,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -173,9 +175,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iel = 0; iel < mesh->n_elements; ++iel) { for (int iel = 0; iel < mesh->n_elements; ++iel) {
double m = 0; double m = 0;
const int *el = &mesh->elements[iel*N_N]; const int *el = &mesh->elements[iel*N_N];
for (int in = 0; in < N_SF; ++in) { for (int in = 0; in < element->nlocal; ++in) {
for (int jn = 0; jn < N_SF; ++jn) { for (int jn = 0; jn < element->nlocal; ++jn) {
problem->concentration[iel*N_SF+in] += invmassmatrix[in][jn]*rhs[iel*N_SF+jn]/det[iel]*dt; problem->concentration[iel*element->nlocal+in] += invmassmatrix[in][jn]*rhs[iel*element->nlocal+jn]/det[iel]*dt;
} }
} }
...@@ -220,6 +222,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) { ...@@ -220,6 +222,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
free(rhs); free(rhs);
free(det); free(det);
#endif
} }
void fluid_problem_set_concentration_cg(FluidProblem *problem, double *concentration) { void fluid_problem_set_concentration_cg(FluidProblem *problem, double *concentration) {
......
#ifndef FLUID_PROBLEM_FEM_H
#define FLUID_PROBLEM_FEM_H
#define D DIMENSION #define D DIMENSION
#include <math.h> #include <math.h>
#include "mesh.h"
#define deps 1 #define deps 1
#if D==2 struct FEElementStruct{
int nlocal;
int n[DIMENSION+1];
void (*f)(const double *xi, double *f);
void (*df)(const double *xi, const double dxidx[D][D], double f[][D]);
};
FEElement *fe_element_new(const char *etype);
void fe_element_free(FEElement *element);
#define N_SF 3 typedef struct {
#define N_N 3 int local_size;
int n;
int nd[DIMENSION+1];
FEElement **element;
}FEFields;
FEFields *fe_fields_new(const char **etypes);
void fe_fields_f(const FEFields *fields, const double *xi, double *f);
void fe_fields_df(const FEFields *fields, const double *xi, const double dxdidx[D][D], double df[][D]);
void fe_fields_eval_grad(const FEFields *fields, const Mesh *mesh, int iel, const double sf[], const double dsf[][DIMENSION], const double *v, double s[], double ds[][DIMENSION]);
void fe_fields_eval(const FEFields *fields, const Mesh *mesh, int iel, const double sf[], const double *v, double s[]);
void fe_fields_add_to_local_vector(const FEFields *fields, const double *f0, const double f1[][D], const double *sf, const double dsf[][D], double jw, double *local_vector);
static void fe_fields_add_to_local_matrix(const FEFields *fields, const double *f00, const double f01[][D], const double f10[][D], const double f11[][D][D], const double *sf, const double dsf[][D], double jw, double *local_matrix) {
int jc = 0;
for (int jfield = 0; jfield < fields->n; ++jfield) {
for (int jphi = 0; jphi < fields->element[jfield]->nlocal; ++jphi){
int ic = 0;
for (int ifield = 0; ifield < fields->n; ++ifield){
for (int iphi = 0; iphi < fields->element[ifield]->nlocal; ++iphi){
double m = 0;
if (f00) {
m += jw*sf[ic]*sf[jc]*f00[ifield*fields->n+jfield];
}
if (f10) {
for (int id = 0; id < D; ++id) {
m += jw*dsf[ic][id]*sf[jc]*f10[ifield*fields->n+jfield][id];
}
}
if (f11) {
for (int id = 0; id < D; ++id) {
for (int jd = 0; jd < D; ++jd) {
m += jw*dsf[ic][id]*dsf[jc][jd]*f11[ifield*fields->n+jfield][id][jd];
}
}
}
if (f01) {
for (int jd = 0; jd < D; ++jd) {
m += jw*sf[ic]*dsf[jc][jd]*f01[ifield*fields->n+jfield][jd];
}
}
local_matrix[(ifield*3+iphi)*9+jfield*3+jphi] += m;
ic ++;
}
}
jc ++;
}
}
}
void fe_fields_free(FEFields *fields);
#if D==2
#define N_QP 3 #define N_QP 3
#define N_LQP 2 #define N_LQP 2
#define N_LSF 2
static double LQP[][1] = {{0.21132486540518713}, {0.7886751345948129}}; static double LQP[][1] = {{0.21132486540518713}, {0.7886751345948129}};
static double LQW[] = {0.5,0.5}; static double LQW[] = {0.5,0.5};
static double QP[][2] = {{1./6,1./6},{1./6,2./3},{2./3,1./6}}; static double QP[][2] = {{1./6,1./6},{1./6,2./3},{2./3,1./6}};
static double QW[] = {1./6,1./6,1./6}; static double QW[] = {1./6,1./6,1./6};
static void shape_functions(double *uvw, double *sf)
{
sf[0] = 1-uvw[0]-uvw[1];
sf[1] = uvw[0];
sf[2] = uvw[1];
}
static void grad_shape_functions(const double dxidx[2][2], double gsf[3][2])
{
for (int i = 0; i < 2; ++i) {
gsf[0][i] = -dxidx[0][i]-dxidx[1][i];
gsf[1][i] = dxidx[0][i];
gsf[2][i] = dxidx[1][i];
}
}
static double detDD(const double m[2][2]) static double detDD(const double m[2][2])
{ {
return m[0][0]*m[1][1] - m[0][1]*m[1][0]; return m[0][0]*m[1][1] - m[0][1]*m[1][0];
...@@ -41,10 +88,7 @@ static double invDD(const double m[2][2], double inv[2][2]) ...@@ -41,10 +88,7 @@ static double invDD(const double m[2][2], double inv[2][2])
inv[1][1] = m[0][0]/d; inv[1][1] = m[0][0]/d;
return d; return d;
} }
static void l_shape_functions(double *uvw, double *sf) {
sf[0] = 1-uvw[0];
sf[1] = uvw[0];
}
static const double invmassmatrix[3][3] = { static const double invmassmatrix[3][3] = {
{18,-6,-6}, {18,-6,-6},
{-6,18,-6}, {-6,18,-6},
...@@ -55,6 +99,18 @@ static const double mass_matrix[3][3] = { ...@@ -55,6 +99,18 @@ static const double mass_matrix[3][3] = {
{1./24,1./12,1./24}, {1./24,1./12,1./24},
{1./24,1./24,1./12} {1./24,1./24,1./12}
}; };
static double get_normal(const Mesh *mesh, const int *interface, double n[2]){
const int *tri = &mesh->elements[interface[0]*3];
const int *cl = elbnd2[interface[1]];
double *x[2] = {&mesh->x[tri[cl[0]]*3], &mesh->x[tri[cl[1]]*3]};
const double dx[2] = {x[1][0]-x[0][0], x[1][1]-x[0][1]};
const double detbnd = sqrt(dx[0]*dx[0] + dx[1]*dx[1]);
n[0] = dx[1]/detbnd;
n[1] = -dx[0]/detbnd;
return detbnd;
}
static void get_normal_and_det(double *x[2], double n[2], double *det){ static void get_normal_and_det(double *x[2], double n[2], double *det){
const double dx[2] = {x[1][0]-x[0][0], x[1][1]-x[0][1]}; const double dx[2] = {x[1][0]-x[0][0], x[1][1]-x[0][1]};
const double detbnd = sqrt(dx[0]*dx[0] + dx[1]*dx[1]); const double detbnd = sqrt(dx[0]*dx[0] + dx[1]*dx[1]);
...@@ -62,13 +118,11 @@ static void get_normal_and_det(double *x[2], double n[2], double *det){ ...@@ -62,13 +118,11 @@ static void get_normal_and_det(double *x[2], double n[2], double *det){
n[1] = -dx[0]/detbnd; n[1] = -dx[0]/detbnd;
*det = detbnd; *det = detbnd;
} }
#else #else
#define N_SF 4
#define N_N 4
#define N_QP 5 #define N_QP 5
#define N_LQP 3 #define N_LQP 3
#define N_LSF 3
static double QP[][3] = { static double QP[][3] = {
{0.25, 0.25, 0.25}, {0.25, 0.25, 0.25},
{0.5, 1./6, 1./6}, {0.5, 1./6, 1./6},
...@@ -79,22 +133,6 @@ static double QP[][3] = { ...@@ -79,22 +133,6 @@ static double QP[][3] = {
static double LQP[][2] = {{1./6,1./6},{1./6,2./3},{2./3,1./6}}; static double LQP[][2] = {{1./6,1./6},{1./6,2./3},{2./3,1./6}};
static double QW[] = {-16./120, 9./120, 9./120, 9./120, 9./120}; static double QW[] = {-16./120, 9./120, 9./120, 9./120, 9./120};
static double LQW[] = {1./6,1./6,1./6}; static double LQW[] = {1./6,1./6,1./6};
static void shape_functions(double *uvw, double *sf)
{
sf[0] = 1-uvw[0]-uvw[1]-uvw[2];
sf[1] = uvw[0];
sf[2] = uvw[1];
sf[3] = uvw[2];
}
static void grad_shape_functions(const double dxidx[3][3], double gsf[4][3])
{
for (int i = 0; i < 3; ++i) {
gsf[0][i] = -dxidx[0][i]-dxidx[1][i]-dxidx[2][i];
gsf[1][i] = dxidx[0][i];
gsf[2][i] = dxidx[1][i];
gsf[3][i] = dxidx[2][i];
}
};
static double detDD(const double m[3][3]) static double detDD(const double m[3][3])
{ {
return m[0][0]*(m[1][1]*m[2][2]-m[2][1]*m[1][2]) return m[0][0]*(m[1][1]*m[2][2]-m[2][1]*m[1][2])
...@@ -115,11 +153,6 @@ static double invDD(const double m[3][3], double inv[3][3]) { ...@@ -115,11 +153,6 @@ static double invDD(const double m[3][3], double inv[3][3]) {
return d; return d;
}; };
static void l_shape_functions(double *uvw, double *sf) {
sf[0] = 1-uvw[0]-uvw[1];
sf[1] = uvw[0];
sf[2] = uvw[1];
}
static const double invmassmatrix[4][4] = { static const double invmassmatrix[4][4] = {
{ 96,-24,-24,-24}, { 96,-24,-24,-24},
{-24, 96,-24,-24}, {-24, 96,-24,-24},
...@@ -145,5 +178,21 @@ static void get_normal_and_det(double *x[3], double n[3], double *det) { ...@@ -145,5 +178,21 @@ static void get_normal_and_det(double *x[3], double n[3], double *det) {
*det = detbnd; *det = detbnd;
} }
#endif static double get_normal(const Mesh *mesh, const int *interface, double n[3]){
const int *tet = &mesh->elements[interface[0]*4];
const int *cl = elbnd2[interface[1]];
double *x[3] = {&mesh->x[tet[cl[0]]*3], &mesh->x[tet[cl[1]]*3], &mesh->x[tet[cl[2]]*3]};
const double dx[2][3] = {{x[1][0]-x[0][0], x[1][1]-x[0][1], x[1][2]-x[0][2]},{x[2][0]-x[0][0], x[2][1]-x[0][1], x[2][2]-x[0][2]}};
const double nn[3] = {
dx[0][1]*dx[1][2] - dx[0][2]*dx[1][1],
dx[0][2]*dx[1][0] - dx[0][0]*dx[1][2],
dx[0][0]*dx[1][1] - dx[0][1]*dx[1][0]};
const double detbnd = sqrt(nn[0]*nn[0] + nn[1]*nn[1] + nn[2]*nn[2]);
n[0] = -nn[0]/detbnd;
n[1] = -nn[1]/detbnd;
n[2] = -nn[2]/detbnd;
return detbnd;
}
#endif
#endif
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
#include "mesh.h" #include "mesh.h"
#include "fluid_problem_fem.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
...@@ -74,7 +75,7 @@ static void mesh_gen_edges(Mesh *m, int n_bnd_elements, int *bnd_elements, int * ...@@ -74,7 +75,7 @@ static void mesh_gen_edges(Mesh *m, int n_bnd_elements, int *bnd_elements, int *
for (int i=0; i<m->n_elements; ++i) { for (int i=0; i<m->n_elements; ++i) {
for (int j = 0; j < DIMENSION+1; ++j) { for (int j = 0; j < DIMENSION+1; ++j) {
for (int k = 0; k < DIMENSION; ++k) { for (int k = 0; k < DIMENSION; ++k) {
he->n[k] = m->elements[i*(DIMENSION+1)+elbnd[j][k]]; he->n[k] = m->elements[i*(DIMENSION+1)+elbnd2[j][k]];
} }
sort_edge_nodes(he->n); sort_edge_nodes(he->n);
he->element = i; he->element = i;
...@@ -139,10 +140,10 @@ static void mesh_gen_edges(Mesh *m, int n_bnd_elements, int *bnd_elements, int * ...@@ -139,10 +140,10 @@ static void mesh_gen_edges(Mesh *m, int n_bnd_elements, int *bnd_elements, int *
const int *e1 = &m->elements[e[2]*4]; const int *e1 = &m->elements[e[2]*4];
e[3] += 12; e[3] += 12;
if (periodic) { if (periodic) {
while (m->periodic_mapping[e0[elbnd[e[1]][0]]] != m->periodic_mapping[e1[elbnd[e[3]][k]]]) e[3] += 4; while (m->periodic_mapping[e0[elbnd2[e[1]][0]]] != m->periodic_mapping[e1[elbnd2[e[3]][k]]]) e[3] += 4;
} }
else { else {
while (e0[elbnd[e[1]][0]] != e1[elbnd[e[3]][k]]) e[3] += 4; while (e0[elbnd2[e[1]][0]] != e1[elbnd2[e[3]][k]]) e[3] += 4;
} }
#endif #endif
} }
...@@ -161,11 +162,17 @@ void mesh_free(Mesh *m) ...@@ -161,11 +162,17 @@ void mesh_free(Mesh *m)
free(m->boundary_names); free(m->boundary_names);
free(m->interfaces); free(m->interfaces);
free(m->periodic_mapping); free(m->periodic_mapping);
fe_element_free(m->element);
free(m); free(m);
} }
Mesh *mesh_new_from_elements(int n_nodes, double *x, int n_elements, int *elements, int n_boundaries, int *boundaries, int *boundary_tags,int n_physicals, char **physicals, const int *periodic) { Mesh *mesh_new_from_elements(int n_nodes, double *x, int n_elements, int *elements, int n_boundaries, int *boundaries, int *boundary_tags,int n_physicals, char **physicals, const int *periodic) {
Mesh *m = malloc(sizeof(Mesh)); Mesh *m = malloc(sizeof(Mesh));
#if DIMENSION == 2
m->element = fe_element_new("triangle_p1");
#else
m->element = fe_element_new("tetrahedron_p1");