def test_dirichlet_problem_sphere(self, sphere3_msh): m = sphere3_msh.crop_mesh(elm_type=4) cond = np.ones(len(m.elm.tetrahedra)) cond[m.elm.tag1 == 4] = .01 anode = m.nodes.node_number[m.nodes.node_coord[:, 2].argmax()] cathode = m.nodes.node_number[m.nodes.node_coord[:, 2].argmin()] bcs = [fem.DirichletBC([anode], [1]), fem.DirichletBC([cathode], [-1])] S = fem.FEMSystem(m, cond) A = S.A b = np.zeros(m.nodes.nr) dof_map = S.dof_map for bc in bcs: A, b, dof_map = bc.apply(A, b, dof_map) x = spalg.spsolve(A, b) for bc in bcs: x, dof_map = bc.apply_to_solution(x, dof_map) order = dof_map.inverse.argsort() x = x[order].squeeze() v_analytical = analytical_solutions.potential_3layers_surface_electrodes( [85, 90, 95], [1., .01, 1.], [0, 0, -95], [0, 0, 95], m.nodes.node_coord) v_analytical /= v_analytical[anode - 1] v_analytical -= v_analytical[0] x -= x[0] m.nodedata = [mesh_io.NodeData(v_analytical, 'Analytical'), mesh_io.NodeData(x, 'FEM')] #mesh_io.write_msh(m, '~/Tests/fem.msh') m = m.crop_mesh(3) assert rdm(m.nodedata[0].value, m.nodedata[1].value) < .1
def test_tdcs_run(self, mock_fem, sampler_args): mesh, poslist, fn_hdf5, roi = sampler_args v = mesh.nodes.node_coord[:, 0] v_roi = mesh.crop_mesh(roi).nodes.node_coord[:, 0] mock_fem.tdcs.side_effect = [ mesh_io.NodeData(v, mesh=mesh), mesh_io.NodeData(-v, mesh=mesh)] S = simnibs_gpc.TDCSgPCSampler( mesh, poslist, fn_hdf5, [1101, 1102], [-1, 1], roi) S.qoi_function['rand'] = lambda v, rand: rand E1 = S.run_simulation([1]) assert E1.shape == (3 * np.sum(mesh.elm.tag1 == 3), ) assert np.allclose(E1.reshape(-1, 3), [-1e3, 0, 0]) S.run_simulation([2]) with h5py.File(fn_hdf5) as f: assert np.allclose(f['random_var_samples'][()], [[1], [2]]) assert np.allclose(f['mesh_roi/data_matrices/v_samples'][0, :], v_roi) assert np.allclose(f['mesh_roi/data_matrices/v_samples'][1, :],-v_roi) assert np.allclose(f['mesh_roi/data_matrices/E_samples'][0, :],[-1e3, 0., 0.]) assert np.allclose(f['mesh_roi/data_matrices/E_samples'][1, :],[1e3, 0., 0.]) assert np.allclose(f['mesh_roi/data_matrices/rand_samples'][:],[[1], [2]])
def test_calc_dadt(self, sphere3_msh): phi = sphere3_msh.nodes.node_coord[:, 0] + \ 2 * sphere3_msh.nodes.node_coord[:, 1] + \ -3 * sphere3_msh.nodes.node_coord[:, 2] potential = mesh_io.NodeData(phi, mesh=sphere3_msh) dadt = .2 * sphere3_msh.nodes.node_coord dadt = mesh_io.NodeData(dadt, mesh=sphere3_msh) E = np.zeros((sphere3_msh.elm.nr, 3)) E = [-1, -2, 3] - dadt.node_data2elm_data().value E = mesh_io.ElementData(E, mesh=sphere3_msh) E.assign_triangle_values() cond = sphere3_msh.elm.tag1 cond = mesh_io.ElementData(cond, mesh=sphere3_msh) m = fem.calc_fields(potential, 'vDJEgsej', cond, dadt=dadt, units='m') assert np.allclose(m.field['v'].value, potential.value) assert np.allclose(m.field['D'].value, dadt.value) assert np.allclose(m.field['g'].value, [1, 2, -3]) assert np.allclose(m.field['E'].value, E.value) assert np.allclose(m.field['J'].value, cond.value[:, None] * E.value) assert np.allclose(m.field['conductivity'].value, cond.value) assert np.allclose(m.field['normE'].value, np.linalg.norm(E.value, axis=1)) assert np.allclose(m.field['normJ'].value, np.linalg.norm(cond.value[:, None] * E.value, axis=1))
def test_solve_dirichlet_petsc(self, cube_msh): m = cube_msh cond = np.ones(m.elm.nr) cond[m.elm.tag1 > 5] = 1e3 cond = mesh_io.ElementData(cond) el_tags = [1100, 1101] potentials = [1, -1] S = fem.FEMSystem.tdcs(m, cond, el_tags, potentials) x = S.solve() sol = m.nodes.node_coord[:, 1]/50. m.nodedata = [mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical')] #mesh_io.write_msh(m, '~/Tests/fem.msh') assert rdm(sol, x.T) < .1 assert np.abs(mag(x, sol)) < np.log(1.1)
def test_solve_assemble_neumann_petsc(self, cube_msh): m = cube_msh cond = np.ones(m.elm.nr) cond[m.elm.tag1 > 5] = 25 cond = mesh_io.ElementData(cond) el_tags = [1100, 1101] currents = [1, -1] S = fem.FEMSystem.tdcs_neumann(m, cond, el_tags[0]) b = S.assemble_tdcs_neumann_rhs(el_tags[1:], currents[1:]) x = S.solve(b) sol = (m.nodes.node_coord[:, 1] - 50) / 10 m.nodedata = [mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical')] #mesh_io.write_msh(m, '~/Tests/fem.msh') assert rdm(sol, x.T) < .1 assert np.abs(mag(x, sol)) < np.log(1.5)
def test_solve_petsc(self, tms_sphere): m, cond, dAdt, E_analytical = tms_sphere S = fem.FEMSystem.tms(m, cond) b = S.assemble_tms_rhs(dAdt) x = S.solve(b) v = mesh_io.NodeData(x, 'FEM', mesh=m) E = -v.gradient().value * 1e3 - dAdt.node_data2elm_data().value m.elmdata = [mesh_io.ElementData(E_analytical, 'analytical'), mesh_io.ElementData(E, 'E_FEM'), mesh_io.ElementData(E_analytical + dAdt.node_data2elm_data().value, 'grad_analytical'), dAdt] m.nodedata = [mesh_io.NodeData(x, 'FEM')] #mesh_io.write_msh(m, '~/Tests/fem.msh') assert rdm(E, E_analytical) < .2 assert np.abs(mag(E, E_analytical)) < np.log(1.1)
def test_avoid_mean_field_norm_node(self, sphere_surf): a = opt_struct.TDCSavoid(tissues=[1003], weight=1e4, lf_type='node', mesh=sphere_surf) field = mesh_io.NodeData(np.ones((sphere_surf.nodes.nr, 3))) assert np.isclose(a.mean_field_norm_in_region(field), np.sqrt(3))
def test_calc_vEJgs(self, sphere3_msh): phi = sphere3_msh.nodes.node_coord[:, 0] + \ 2 * sphere3_msh.nodes.node_coord[:, 1] + \ -3 * sphere3_msh.nodes.node_coord[:, 2] potential = mesh_io.NodeData(phi, mesh=sphere3_msh) E = np.zeros((sphere3_msh.elm.nr, 3)) E[:] = [-1., -2., 3.] E = mesh_io.ElementData(E, mesh=sphere3_msh) cond = sphere3_msh.elm.tag1 cond = mesh_io.ElementData(cond, mesh=sphere3_msh) m = fem.calc_fields(potential, 'vJEgsej', cond) assert np.allclose(m.field['v'].value, potential.value) assert np.allclose(m.field['E'].value, E.value * 1e3) assert np.allclose(m.field['J'].value, cond.value[:, None] * E.value * 1e3) assert np.allclose(m.field['g'].value, -E.value * 1e3) assert np.allclose(m.field['conductivity'].value, cond.value) assert np.allclose(m.field['normE'].value, np.linalg.norm(E.value, axis=1) * 1e3) assert np.allclose( m.field['normJ'].value, np.linalg.norm(cond.value[:, None] * E.value, axis=1) * 1e3)
def test_solve_assemble_aniso(self, cube_msh): m = cube_msh cond = np.tile(np.eye(3), (m.elm.nr, 1, 1)) cond[m.elm.tag1 > 5] *= 100 cond[m.elm.tag1 < 5, 0, :] = 0.01 cond[m.elm.tag1 < 5, 1, :] = 0.1 cond = mesh_io.ElementData(cond.reshape(-1, 9)) el_tags = [1100, 1101] currents = [1, -1] S = fem.FEMSystem.tdcs_neumann(m, cond, el_tags[0]) b = S.assemble_tdcs_neumann_rhs(el_tags[1:], currents[1:]) x = S.solve(b) sol = (m.nodes.node_coord[:, 1] - 50) / 10 m.nodedata = [mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical')] #mesh_io.write_msh(m, '~/Tests/fem.msh') assert rdm(sol, x.T) < .1 assert np.abs(mag(x, sol)) < np.log(1.5)
def test_solve_assemble_neumann_nodes(self, cube_msh): m = cube_msh cond = np.ones(m.elm.nr) cond[m.elm.tag1 > 5] = 25 cond = mesh_io.ElementData(cond) currents = [1, -1] nodes_top = np.unique(m.elm[m.elm.tag1 == 1100, :3]) nodes_bottom = np.unique(m.elm[m.elm.tag1 == 1101, :3]) S = fem.FEMSystem.tdcs_neumann(m, cond, nodes_top, input_type='node') b = S.assemble_tdcs_neumann_rhs(nodes_bottom, currents[1:], input_type='node') x = S.solve(b) sol = (m.nodes.node_coord[:, 1] - 50) / 10 m.nodedata = [ mesh_io.NodeData(x, 'FEM'), mesh_io.NodeData(sol, 'Analytical') ] #mesh_io.write_msh(m, '~/Tests/fem.msh') assert rdm(sol, x.T) < .1 assert np.abs(mag(x, sol)) < np.log(1.5)
def test_tdcs_neumann_3_el(self, cube_msh): m = cube_msh cond = np.ones(m.elm.nr) cond[m.elm.tag1 > 5] = 1e3 cond = mesh_io.ElementData(cond) el_tags = [1100, 1101, 1101] currents = [.5, -1.5, 1.] x = fem.tdcs_neumann(m, cond, currents, el_tags) sol = (m.nodes.node_coord[:, 1] - 50) / 20 m.nodedata = [x, mesh_io.NodeData(sol, 'Analytical')] #mesh_io.write_msh(m, '~/Tests/fem.msh') assert rdm(sol, x.value) < .1 assert np.abs(mag(x.value, sol)) < np.log(1.1)
def tms_sphere(sphere3_msh): m = sphere3_msh.crop_mesh(elm_type=4) dipole_pos = np.array([0., 0., 300]) dipole_moment = np.array([1., 0., 0.]) didt = 1e6 r = (m.nodes.node_coord - dipole_pos) * 1e-3 dAdt = 1e-7 * didt * np.cross(dipole_moment, r) / (np.linalg.norm(r, axis=1)[:, None] ** 3) dAdt = mesh_io.NodeData(dAdt, mesh=m) dAdt.field_name = 'dAdt' dAdt.mesh = m pos = m.elements_baricenters().value E_analytical = analytical_solutions.tms_E_field(dipole_pos * 1e-3, dipole_moment, didt, pos * 1e-3) cond = mesh_io.ElementData(np.ones(m.elm.nr)) cond.mesh = m return m, cond, dAdt, E_analytical
def test_calc_tensor(self, sphere3_msh): phi = sphere3_msh.nodes.node_coord[:, 0] + \ 2 * sphere3_msh.nodes.node_coord[:, 1] + \ -3 * sphere3_msh.nodes.node_coord[:, 2] potential = mesh_io.NodeData(phi, mesh=sphere3_msh) o = np.ones(sphere3_msh.elm.nr) z = np.zeros(sphere3_msh.elm.nr) cond = np.reshape(np.eye(3) * np.array([1, 2, 3]), -1) cond = np.tile(cond, [sphere3_msh.elm.nr, 1]) cond = mesh_io.ElementData(cond, mesh=sphere3_msh) m = fem.calc_fields(potential, 'vJEgsej', cond, units='m') assert np.allclose(m.field['v'].value, potential.value) assert np.allclose(m.field['g'].value, [1, 2, -3]) assert np.allclose(m.field['E'].value, [-1, -2, 3]) assert np.allclose(m.field['J'].value, [-1, -4, 9])
def test_calc_E(self, sampler_args): mesh, poslist, fn_hdf5, roi = sampler_args S = simnibs_gpc.gPCSampler(mesh, poslist, fn_hdf5, roi) v = mesh_io.NodeData(mesh.nodes.node_coord[:, 0], mesh=mesh) E = S._calc_E(v, None) assert np.allclose(E, [-1e3, 0, 0])