forked from solveignaess/fourspheremodel
-
Notifications
You must be signed in to change notification settings - Fork 4
/
numerical_fem.py
95 lines (83 loc) · 3.55 KB
/
numerical_fem.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import os
import numpy as np
from dolfin import *
import parameters as params
def extract_pots(phi, positions):
compt_values = np.zeros(positions.shape[0])
for ii in range(positions.shape[0]):
compt_values[ii] = phi(positions[ii, :])
return compt_values
def main_4shell_fem(mesh, subdomains, boundaries, skull_cond, src_pos, snk_pos):
sigma_B = Constant(params.sigma_brain)
sigma_Sc = Constant(params.sigma_scalp)
sigma_C = Constant(params.sigma_csf)
sigma_Sk = Constant(skull_cond)
sigma_A = Constant(0.)
V = FunctionSpace(mesh, "CG", 2)
v = TestFunction(V)
u = TrialFunction(V)
phi = Function(V)
dx = Measure("dx")(subdomain_data=subdomains)
ds = Measure("ds")(subdomain_data=boundaries)
a = inner(sigma_B * grad(u), grad(v))*dx(params.whitemattervol) + \
inner(sigma_B * grad(u), grad(v))*dx(params.graymattervol) + \
inner(sigma_Sc * grad(u), grad(v))*dx(params.scalpvol) + \
inner(sigma_C * grad(u), grad(v))*dx(params.csfvol) + \
inner(sigma_Sk * grad(u), grad(v))*dx(params.skullvol)
L = Constant(0)*v*dx
A = assemble(a)
b = assemble(L)
x_pos, y_pos, z_pos = src_pos
point = Point(x_pos, y_pos, z_pos)
delta = PointSource(V, point, 1.)
delta.apply(b)
x_pos, y_pos, z_pos = snk_pos
point1 = Point(x_pos, y_pos, z_pos)
delta1 = PointSource(V, point1, -1.)
delta1.apply(b)
solver = KrylovSolver("cg", "ilu")
solver.parameters["maximum_iterations"] = 1000
solver.parameters["absolute_tolerance"] = 1E-8
solver.parameters["monitor_convergence"] = True
info(solver.parameters, True)
# set_log_level(PROGRESS) does not work in fenics 2018.1.0
solver.solve(A, phi.vector(), b)
ele_pos_list = params.ele_coords
vals = extract_pots(phi, ele_pos_list)
# np.save(os.path.join('results', save_as), vals)
return vals
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('mesh', nargs='?',
default=os.path.join('mesh', 'sphere_4.xml'),
help='a path to the XML file with the mesh')
parser.add_argument('--directory', '-d',
default='results',
dest='results',
help='a path to the result directory')
args = parser.parse_args()
if not os.path.exists(args.results):
os.makedirs(args.results)
print('Loading meshes')
mesh = Mesh(args.mesh)
subdomains = MeshFunction("size_t", mesh, args.mesh[:-4] + '_physical_region.xml')
boundaries = MeshFunction("size_t", mesh, args.mesh[:-4] + '_facet_region.xml')
for dipole in params.dipole_list:
print('Now computing FEM for dipole: ', dipole['name'])
src_pos = dipole['src_pos']
snk_pos = dipole['snk_pos']
print('Done loading meshes')
fem_20 = main_4shell_fem(mesh, subdomains, boundaries,
params.sigma_skull20, src_pos, snk_pos)
print('Done 4Shell-FEM-20')
fem_40 = main_4shell_fem(mesh, subdomains, boundaries,
params.sigma_skull40, src_pos, snk_pos)
print('Done 4Shell-FEM-40')
fem_80 = main_4shell_fem(mesh, subdomains, boundaries,
params.sigma_skull80, src_pos, snk_pos)
print('Done 4Shell-FEM-80')
f = open(os.path.join(args.results,
'Numerical_' + dipole['name'] + '.npz'), 'wb')
np.savez(f, fem_20=fem_20, fem_40=fem_40, fem_80=fem_80)
f.close()