CoreNEURON
lfp.cpp
Go to the documentation of this file.
1 #include "coreneuron/io/lfp.hpp"
3 
4 #include <cmath>
5 #include <limits>
6 #include <sstream>
7 
8 
9 namespace coreneuron {
10 namespace lfputils {
11 
12 double line_source_lfp_factor(const Point3D& e_pos,
13  const Point3D& seg_0,
14  const Point3D& seg_1,
15  const double radius,
16  const double f) {
17  nrn_assert(radius >= 0.0);
18  Point3D dx = paxpy(seg_1, -1.0, seg_0);
19  Point3D de = paxpy(e_pos, -1.0, seg_0);
20  double dx2(dot(dx, dx));
21  double dxn(std::sqrt(dx2));
22  if (dxn < std::numeric_limits<double>::epsilon()) {
23  return point_source_lfp_factor(e_pos, seg_0, radius, f);
24  }
25  double de2(dot(de, de));
26  double mu(dot(dx, de) / dx2);
27  Point3D de_star(paxpy(de, -mu, dx));
28  double de_star2(dot(de_star, de_star));
29  double q2(de_star2 / dx2);
30 
31  double delta(mu * mu - (de2 - radius * radius) / dx2);
32  double one_m_mu(1.0 - mu);
33  auto log_integral = [&q2, &dxn](double a, double b) {
34  if (q2 < std::numeric_limits<double>::epsilon()) {
35  if (a * b <= 0) {
36  std::ostringstream s;
37  s << "Log integral: invalid arguments " << b << " " << a
38  << ". Likely electrode exactly on the segment and "
39  << "no flooring is present.";
40  throw std::invalid_argument(s.str());
41  }
42  return std::abs(std::log(b / a)) / dxn;
43  } else {
44  return std::log((b + std::sqrt(b * b + q2)) / (a + std::sqrt(a * a + q2))) / dxn;
45  }
46  };
47  if (delta <= 0.0) {
48  return f * log_integral(-mu, one_m_mu);
49  } else {
50  double sqr_delta(std::sqrt(delta));
51  double d1(mu - sqr_delta);
52  double d2(mu + sqr_delta);
53  double parts = 0.0;
54  if (d1 > 0.0) {
55  double b(std::min(d1, 1.0) - mu);
56  parts += log_integral(-mu, b);
57  }
58  if (d2 < 1.0) {
59  double b(std::max(d2, 0.0) - mu);
60  parts += log_integral(b, one_m_mu);
61  };
62  // complement
63  double maxd1_0(std::max(d1, 0.0)), mind2_1(std::min(d2, 1.0));
64  if (maxd1_0 < mind2_1) {
65  parts += 1.0 / radius * (mind2_1 - maxd1_0);
66  }
67  return f * parts;
68  };
69 }
70 } // namespace lfputils
71 
72 using namespace lfputils;
73 
74 template <LFPCalculatorType Type, typename SegmentIdTy>
76  const Point3Ds& seg_end,
77  const std::vector<double>& radius,
78  const std::vector<SegmentIdTy>& segment_ids,
79  const Point3Ds& electrodes,
80  double extra_cellular_conductivity)
81  : segment_ids_(segment_ids) {
82  if (seg_start.size() != seg_end.size()) {
83  throw std::invalid_argument("Different number of segment starts and ends.");
84  }
85  if (seg_start.size() != radius.size()) {
86  throw std::invalid_argument("Different number of segments and radii.");
87  }
88  double f(1.0 / (extra_cellular_conductivity * 4.0 * pi));
89 
90  m.resize(electrodes.size());
91  for (size_t k = 0; k < electrodes.size(); ++k) {
92  auto& ms = m[k];
93  ms.resize(seg_start.size());
94  for (size_t l = 0; l < seg_start.size(); l++) {
95  ms[l] = getFactor(electrodes[k], seg_start[l], seg_end[l], radius[l], f);
96  }
97  }
98 }
99 
100 template <LFPCalculatorType Type, typename SegmentIdTy>
101 template <typename Vector>
102 inline void LFPCalculator<Type, SegmentIdTy>::lfp(const Vector& membrane_current) {
103  std::vector<double> res(m.size());
104  for (size_t k = 0; k < m.size(); ++k) {
105  res[k] = 0.0;
106  auto& ms = m[k];
107  for (size_t l = 0; l < ms.size(); l++) {
108  res[k] += ms[l] * membrane_current[segment_ids_[l]];
109  }
110  }
111 #if NRNMPI
113  lfp_values_.resize(res.size());
114  int mpi_sum{1};
115  nrnmpi_dbl_allreduce_vec(res.data(), lfp_values_.data(), res.size(), mpi_sum);
116  } else
117 #endif
118  {
119  std::swap(res, lfp_values_);
120  }
121 }
122 
123 
125  const lfputils::Point3Ds& seg_end,
126  const std::vector<double>& radius,
127  const std::vector<int>& segment_ids,
128  const lfputils::Point3Ds& electrodes,
129  double extra_cellular_conductivity);
131  const lfputils::Point3Ds& seg_end,
132  const std::vector<double>& radius,
133  const std::vector<int>& segment_ids,
134  const lfputils::Point3Ds& electrodes,
135  double extra_cellular_conductivity);
136 template void LFPCalculator<LineSource>::lfp(const DoublePtr& membrane_current);
137 template void LFPCalculator<PointSource>::lfp(const DoublePtr& membrane_current);
138 template void LFPCalculator<LineSource>::lfp(const std::vector<double>& membrane_current);
139 template void LFPCalculator<PointSource>::lfp(const std::vector<double>& membrane_current);
140 
141 } // namespace coreneuron
coreneuron::lfputils::Point3Ds
std::vector< Point3D > Point3Ds
Definition: lfp.hpp:15
coreneuron::LFPCalculator::getFactor
double getFactor(const lfputils::Point3D &e_pos, const lfputils::Point3D &seg_0, const lfputils::Point3D &seg_1, const double radius, const double f) const
coreneuron::lfputils::DoublePtr
double * DoublePtr
Definition: lfp.hpp:16
coreneuron::LFPCalculator::lfp
void lfp(const Vector &membrane_current)
Definition: lfp.cpp:102
coreneuron::lfputils::dot
double dot(const Point3D &p1, const Point3D &p2)
Definition: lfp.hpp:18
coreneuron
THIS FILE IS AUTO GENERATED DONT MODIFY IT.
Definition: corenrn_parameters.cpp:12
corenrn_parameters.hpp
coreneuron::corenrn_param
corenrn_parameters corenrn_param
Printing method.
Definition: corenrn_parameters.cpp:268
coreneuron::lfputils::point_source_lfp_factor
double point_source_lfp_factor(const Point3D &e_pos, const Point3D &seg_pos, const double radius, const double f)
Definition: lfp.hpp:42
coreneuron::lfputils::line_source_lfp_factor
double line_source_lfp_factor(const Point3D &e_pos, const Point3D &seg_0, const Point3D &seg_1, const double radius, const double f)
Definition: lfp.cpp:12
coreneuron::lfputils::Point3D
std::array< double, 3 > Point3D
Definition: lfp.hpp:14
coreneuron::corenrn_parameters_data::mpi_enable
bool mpi_enable
Initialization seed for random number generator (int)
Definition: corenrn_parameters.hpp:59
coreneuron::lfputils::paxpy
Point3D paxpy(const Point3D &p1, const double alpha, const Point3D &p2)
Definition: lfp.hpp:30
coreneuron::LFPCalculator::LFPCalculator
LFPCalculator(const lfputils::Point3Ds &seg_start, const lfputils::Point3Ds &seg_end, const std::vector< double > &radius, const std::vector< SegmentIdTy > &segment_ids, const lfputils::Point3Ds &electrodes, double extra_cellular_conductivity)
LFP Calculator constructor.
Definition: lfp.cpp:75
lfp.hpp
coreneuron::pi
double pi
Definition: register_mech.cpp:22
coreneuron::nrnmpi_dbl_allreduce_vec
mpi_function< cnrn_make_integral_constant_t(nrnmpi_dbl_allreduce_vec_impl)> nrnmpi_dbl_allreduce_vec
Definition: nrnmpidec.cpp:46
nrn_assert
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
coreneuron::LFPCalculator::m
std::vector< std::vector< double > > m
Definition: lfp.hpp:104