Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
fluidparticles
MigFlow
Commits
eec68ea7
Commit
eec68ea7
authored
Jul 07, 2021
by
Jonathan Lambrechts
Browse files
introduce FEElement and FEFields
parent
b40fadaa
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
fluid/CMakeLists.txt
View file @
eec68ea7
...
...
@@ -23,6 +23,7 @@
set
(
SRC
fluid_problem.c
fluid_problem_concentration.c
fluid_problem_fem.c
mesh.c
mesh_find.c
../tools/quadtree.c
...
...
fluid/fluid_problem.c
View file @
eec68ea7
This diff is collapsed.
Click to expand it.
fluid/fluid_problem.h
View file @
eec68ea7
...
...
@@ -26,6 +26,7 @@
#include
"mesh.h"
#include
"mesh_find.h"
#include
"fluid_problem_fem.h"
#if DIMENSION==2
#define N_N 3
...
...
@@ -35,7 +36,6 @@
typedef
void
BoundaryCallback
(
int
n
,
const
double
*
x
,
double
*
bnd
);
typedef
struct
{
char
*
tag
;
int
row
;
...
...
@@ -101,6 +101,7 @@ struct FluidProblem {
int
advection
;
int
temporal
;
int
drag_in_stab
;
FEFields
*
fields
,
*
field_porosity
,
*
field_concentration
;
};
// complete force on the particle (including gravity)
...
...
@@ -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
);
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_bnd
(
FluidProblem
*
problem
,
double
dt
);
void
weak_boundary_values
(
const
Mesh
*
mesh
,
const
MeshBoundary
*
bnd
,
const
WeakBoundary
*
wbnd
,
double
*
data
);
#endif
fluid/fluid_problem_concentration.c
View file @
eec68ea7
...
...
@@ -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
)
{
#if 0
const FEElement *element = problem->fields->element[0];
const Mesh *mesh = problem->mesh;
const int n_fields = fluid_problem_n_fields(problem);
double *velocity = malloc(D*problem->mesh->n_nodes*sizeof(double));
...
...
@@ -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];
const double detj = invDD(dxdxi, dxidx);
det[iel] = detj;
grad_shape_functions
(
dxidx
,
dphi
);
element->df(QP[0],
dxidx, dphi);
double da[D] = {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) {
da[id] += dphi[i][id]*problem->concentration[iel*N_N+i];
divu += dphi[i][id]*problem->solution[el[i]*n_fields+id];
...
...
@@ -51,13 +53,13 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
}
for (int iqp = 0; iqp< N_QP; ++iqp) {
double
phi
[
N_SF
];
shape_functions
(
QP
[
iqp
],
phi
);
double phi[
element->nlocal
];
element->f
(QP[iqp],phi);
double u[D] = {0};
double c = 0;
double cold = 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];
c += phi[i]*problem->porosity[el[i]];
cold += phi[i]*problem->oldporosity[el[i]];
...
...
@@ -70,7 +72,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
r -= u[id]*da[id];
}
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;
}
}
...
...
@@ -81,12 +83,12 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
const int iel0 = interface[0];
const int iel1 = interface[2];
if (iel1 < 0) continue;
const
int
*
cl0
=
el
bnd
[
interface
[
1
]];
const
int
*
cl1
=
el
bnd
[
interface
[
3
]];
double
*
x
[
N_LSF
];
const int *cl0 = el
ement->boundaries
[interface[1]];
const int *cl1 = el
ement->boundaries
[interface[3]];
double *x[
element->boundary_element->nlocal
];
const int *el0 = &mesh->elements[iel0*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];
}
double detbnd, n[D];
...
...
@@ -94,9 +96,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iqp = 0; iqp < N_LQP; ++iqp) {
double a0 = 0, a1 = 0, un = 0;
double phil[N_LQP];
l_shape_functions
(
LQP
[
iqp
],
phil
);
element->boundary_element->f
(LQP[iqp],phil);
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];
a1 += problem->concentration[iel1*N_N+cl1[i]]*phil[i];
c += problem->porosity[el0[cl0[i]]]*phil[i];
...
...
@@ -108,7 +110,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
const double r0 = -un*(a-a0);
const double r1 = un*(a-a1);
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[iel1*N_N+cl1[i]] += phil[i]*r1*jw;
}
...
...
@@ -121,7 +123,7 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
if (wbnd->type == BND_WALL) continue;
int n_value = weak_boundary_n_values(wbnd);
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){
printf("concentration should be specified on open boundary %s.",wbnd->tag);
exit(1);
...
...
@@ -129,9 +131,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iinterface = 0; iinterface < bnd->n_interfaces; ++iinterface) {
const int *interface = &mesh->interfaces[bnd->interfaces[iinterface]*4];
const int iel = interface[0];
const
int
*
cl
=
el
bnd
[
interface
[
1
]];
const int *cl = el
ement->boundaries
[interface[1]];
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){
x[i] = &mesh->x[el[cl[i]]*3];
}
...
...
@@ -140,10 +142,10 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iqp = 0; iqp < N_LQP; ++iqp) {
const double *dataqp = &data[n_value*(iinterface*N_LQP+iqp)];
double phil[N_LQP];
l_shape_functions
(
LQP
[
iqp
],
phil
);
element->boundary_element->f
(LQP[iqp],phil);
double a = 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];
c += problem->porosity[el[cl[i]]]*phil[i];
}
...
...
@@ -153,14 +155,14 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
un += n[id]*dataqp[wbnd->vid+id];
}
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];
}
}
}
const double jw = LQW[iqp]*detbnd;
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;
}
}
...
...
@@ -173,9 +175,9 @@ void fluid_problem_advance_concentration(FluidProblem *problem, double dt) {
for (int iel = 0; iel < mesh->n_elements; ++iel) {
double m = 0;
const int *el = &mesh->elements[iel*N_N];
for
(
int
in
=
0
;
in
<
N_SF
;
++
in
)
{
for
(
int
jn
=
0
;
jn
<
N_SF
;
++
jn
)
{
problem
->
concentration
[
iel
*
N_SF
+
in
]
+=
invmassmatrix
[
in
][
jn
]
*
rhs
[
iel
*
N_SF
+
jn
]
/
det
[
iel
]
*
dt
;
for (int in = 0; in <
element->nlocal
; ++in) {
for (int jn = 0; jn <
element->nlocal
; ++jn) {
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) {
free(rhs);
free(det);
#endif
}
void
fluid_problem_set_concentration_cg
(
FluidProblem
*
problem
,
double
*
concentration
)
{
...
...
fluid/fluid_problem_fem.h
View file @
eec68ea7
#ifndef FLUID_PROBLEM_FEM_H
#define FLUID_PROBLEM_FEM_H
#define D DIMENSION
#include
<math.h>
#include
"mesh.h"
#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
#define N_N 3
typedef
struct
{
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_LQP 2
#define N_LSF 2
static
double
LQP
[][
1
]
=
{{
0
.
21132486540518713
},
{
0
.
7886751345948129
}};
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
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
])
{
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])
inv
[
1
][
1
]
=
m
[
0
][
0
]
/
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
]
=
{
{
18
,
-
6
,
-
6
},
{
-
6
,
18
,
-
6
},
...
...
@@ -55,6 +99,18 @@ static const double mass_matrix[3][3] = {
{
1
.
/
24
,
1
.
/
12
,
1
.
/
24
},
{
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
){
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
]);
...
...
@@ -62,13 +118,11 @@ static void get_normal_and_det(double *x[2], double n[2], double *det){
n
[
1
]
=
-
dx
[
0
]
/
detbnd
;
*
det
=
detbnd
;
}
#else
#define N_SF 4
#define N_N 4
#define N_QP 5
#define N_LQP 3
#define N_LSF 3
static
double
QP
[][
3
]
=
{
{
0
.
25
,
0
.
25
,
0
.
25
},
{
0
.
5
,
1
.
/
6
,
1
.
/
6
},
...
...
@@ -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
QW
[]
=
{
-
16
.
/
120
,
9
.
/
120
,
9
.
/
120
,
9
.
/
120
,
9
.
/
120
};
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
])
{
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]) {
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
]
=
{
{
96
,
-
24
,
-
24
,
-
24
},
{
-
24
,
96
,
-
24
,
-
24
},
...
...
@@ -145,5 +178,21 @@ static void get_normal_and_det(double *x[3], double n[3], double *det) {
*
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
fluid/mesh.c
View file @
eec68ea7
...
...
@@ -22,6 +22,7 @@
*/
#include
"mesh.h"
#include
"fluid_problem_fem.h"
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
...
...
@@ -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
j
=
0
;
j
<
DIMENSION
+
1
;
++
j
)
{
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
)
+
elbnd
2
[
j
][
k
]];
}
sort_edge_nodes
(
he
->
n
);
he
->
element
=
i
;
...
...
@@ -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
];
e
[
3
]
+=
12
;
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
[
elbnd
2
[
e
[
1
]][
0
]]]
!=
m
->
periodic_mapping
[
e1
[
elbnd
2
[
e
[
3
]][
k
]]])
e
[
3
]
+=
4
;
}
else
{
while
(
e0
[
elbnd
[
e
[
1
]][
0
]]
!=
e1
[
elbnd
[
e
[
3
]][
k
]])
e
[
3
]
+=
4
;
while
(
e0
[
elbnd
2
[
e
[
1
]][
0
]]
!=
e1
[
elbnd
2
[
e
[
3
]][
k
]])
e
[
3
]
+=
4
;
}
#endif
}
...
...
@@ -161,11 +162,17 @@ void mesh_free(Mesh *m)
free
(
m
->
boundary_names
);
free
(
m
->
interfaces
);
free
(
m
->
periodic_mapping
);
fe_element_free
(
m
->
element
);
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
*
m
=
malloc
(
sizeof
(
Mesh
));
#if DIMENSION == 2
m
->
element
=
fe_element_new
(
"triangle_p1"
);
#else
m
->
element
=
fe_element_new
(
"tetrahedron_p1"
);
#endif
m
->
n_elements
=
n_elements
;
m
->
elements
=
malloc
(
n_elements
*
sizeof
(
int
)
*
(
DIMENSION
+
1
));
memcpy
(
m
->
elements
,
elements
,(
DIMENSION
+
1
)
*
sizeof
(
int
)
*
n_elements
);
...
...
@@ -212,7 +219,7 @@ MeshBoundary *mesh_boundaries_create(const Mesh *m) {
if
(
interface
[
2
]
==
-
1
)
{
int
tag
=
interface
[
3
];
int
*
el
=
m
->
elements
+
interface
[
0
]
*
(
DIMENSION
+
1
);
int
*
cl
=
elbnd
[
interface
[
1
]];
int
*
cl
=
elbnd
2
[
interface
[
1
]];
b
[
tag
].
interfaces
[
b
[
tag
].
n_interfaces
++
]
=
i
;
for
(
int
i
=
0
;
i
<
DIMENSION
;
++
i
)
{
b
[
tag
].
nodes
[
b
[
tag
].
n_nodes
++
]
=
el
[
cl
[
i
]];
...
...
@@ -246,3 +253,26 @@ void mesh_boundaries_free(MeshBoundary *bs, int n)
}
void
param_boundary_to_element
(
int
cl
,
const
double
*
xibnd
,
double
*
xiel
)
{
#if DIMENSION == 2
double
x
=
xibnd
[
0
];
switch
(
cl
)
{
case
0
:
xiel
[
0
]
=
x
;
xiel
[
1
]
=
0
;
break
;
case
1
:
xiel
[
0
]
=
1
-
x
;
xiel
[
1
]
=
x
;
break
;
case
2
:
xiel
[
0
]
=
0
;
xiel
[
1
]
=
1
-
x
;
break
;
case
3
:
xiel
[
0
]
=
1
-
x
;
xiel
[
1
]
=
0
;
break
;
case
4
:
xiel
[
0
]
=
x
;
xiel
[
1
]
=
1
-
x
;
break
;
case
5
:
xiel
[
0
]
=
0
;
xiel
[
1
]
=
x
;
break
;
}
#else
static
double
nodes
[
4
][
3
]
=
{{
0
,
0
,
0
},{
1
,
0
,
0
},{
0
,
1
,
0
},{
0
,
0
,
1
}};
double
xi
=
xibnd
[
0
],
eta
=
xibnd
[
1
];
double
phi
[
3
]
=
{
1
-
xi
-
eta
,
xi
,
eta
};
for
(
int
i
=
0
;
i
<
3
;
++
i
)
{
xiel
[
i
]
=
0
;
for
(
int
j
=
0
;
j
<
3
;
++
j
)
{
xiel
[
i
]
+=
phi
[
j
]
*
nodes
[
elbnd2
[
cl
][
j
]][
i
];
}
}
#endif
}
fluid/mesh.h
View file @
eec68ea7
...
...
@@ -26,6 +26,7 @@
#include
<stdio.h>
#include
<stdint.h>
typedef
struct
FEElementStruct
FEElement
;
typedef
struct
{
int
n_nodes
;
...
...
@@ -36,10 +37,11 @@ typedef struct {
char
**
boundary_names
;
int
n_interfaces
;
int
*
interfaces
;
// eid0, closure0, {(eid1, closure1),(-1,phys_id)}
int
n_interfaces_periodic
;
//
same as interfaces but
taking into account the
periodicity
int
n_interfaces_periodic
;
//
edges
taking into account the
int
*
interfaces_periodic
;
// eid0, closure0, {(eid1, closure1),(-1,phys_id)}
int
n_periodic
;
int
*
periodic_mapping
;
// n_nodes
FEElement
*
element
;
}
Mesh
;
void
mesh_free
(
Mesh
*
m
);
...
...
@@ -55,15 +57,12 @@ typedef struct {
int
*
nodes
;
}
MeshBoundary
;
MeshBoundary
*
mesh_boundaries_create
(
const
Mesh
*
m
);
void
mesh_boundaries_free
(
MeshBoundary
*
mbnd
,
int
n
);
#if DIMENSION == 2
static
int
elbnd
[
6
][
2
]
=
{
static
int
elbnd
2
[
6
][
2
]
=
{
{
0
,
1
},{
1
,
2
},{
2
,
0
},
{
1
,
0
},{
2
,
1
},{
0
,
2
}};
#else
static
int
elbnd
[
24
][
3
]
=
{
static
int
elbnd
2
[
24
][
3
]
=
{
{
0
,
1
,
2
},{
0
,
2
,
3
},{
0
,
3
,
1
},{
1
,
3
,
2
},
{
2
,
0
,
1
},{
3
,
0
,
2
},{
1
,
0
,
3
},{
2
,
1
,
3
},
{
1
,
2
,
0
},{
2
,
3
,
0
},{
3
,
1
,
0
},{
3
,
2
,
1
},
...
...
@@ -73,4 +72,8 @@ static int elbnd[24][3] = {
{
1
,
0
,
2
},{
2
,
0
,
3
},{
3
,
0
,
1
},{
3
,
1
,
2
}
};
#endif
void
param_boundary_to_element
(
int
cl
,
const
double
*
xibnd
,
double
*
xiel
);
MeshBoundary
*
mesh_boundaries_create
(
const
Mesh
*
m
);
void
mesh_boundaries_free
(
MeshBoundary
*
mbnd
,
int
n
);
#endif
python/petsclsys.py
View file @
eec68ea7
...
...
@@ -50,8 +50,11 @@ class LinearSystem :
def
local_to_global
(
self
,
localv
,
localm
,
rhs
):
self
.
mat
.
zeroEntries
()
np
.
add
.
at
(
rhs
.
reshape
([
-
1
]),
self
.
idx
,
localv
)
for
e
,
m
in
zip
(
self
.
elements
,
localm
.
reshape
([
-
1
,
self
.
localsize
**
2
]))
:
self
.
mat
.
setValuesBlocked
(
e
,
e
,
m
,
PETSc
.
InsertMode
.
ADD
)
vmap
=
np
.
tile
(
self
.
elements
*
3
,[
1
,
3
])
+
np
.
repeat
(
np
.
arange
(
3
,
dtype
=
np
.
int32
),
3
)[
None
,:]
for
e
,
m
in
zip
(
vmap
,
localm
.
reshape
([
-
1
,
self
.
localsize
**
2
]))
:
self
.
mat
.
setValues
(
e
,
e
,
m
,
PETSc
.
InsertMode
.
ADD
)
#for e,m in zip(self.elements,localm.reshape([-1,self.localsize**2])) :
#self.mat.setValuesBlocked(e,e,m,PETSc.InsertMode.ADD)
self
.
mat
.
assemble
()
def
solve
(
self
,
rhs
)
:
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment