Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FilterElectrogram.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File FilterElectrogram.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Outputs virtual electrograms at specific locations.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
37 #include <iomanip>
39 
40 using namespace std;
41 
42 namespace Nektar
43 {
44 std::string FilterElectrogram::className =
46  "Electrogram",
47  FilterElectrogram::create);
48 
49 /**
50  *
51  */
52 FilterElectrogram::FilterElectrogram(
54  const ParamMap &pParams)
55  : Filter(pSession)
56 {
57  ParamMap::const_iterator it;
58 
59  // OutputFile
60  it = pParams.find("OutputFile");
61  if (it == pParams.end())
62  {
63  m_outputFile = m_session->GetSessionName();
64  }
65  else
66  {
67  ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
68  m_outputFile = it->second;
69  }
70  if (!(m_outputFile.length() >= 4
71  && m_outputFile.substr(m_outputFile.length() - 4) == ".ecg"))
72  {
73  m_outputFile += ".ecg";
74  }
75 
76  // OutputFrequency
77  it = pParams.find("OutputFrequency");
78  if (it == pParams.end())
79  {
81  }
82  else
83  {
84  LibUtilities::Equation equ(m_session, it->second);
85  m_outputFrequency = floor(equ.Evaluate());
86  }
87 
88  // Points
89  it = pParams.find("Points");
90  ASSERTL0(it != pParams.end(), "Missing parameter 'Points'.");
91  m_electrogramStream.str(it->second);
92  m_index = 0;
93 }
94 
95 
96 /**
97  *
98  */
100 {
101 
102 }
103 
104 
105 /**
106  *
107  */
110  const NekDouble &time)
111 {
113  "No history points in stream.");
114 
115  m_index = 0;
116  Array<OneD, NekDouble> gloCoord(3,0.0);
117  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
118 
119  // Read electrogram points
120  // Always use dim = 3 to allow electrode to be above surface
121  const int dim = 3;
122  int i = 0;
123 
124  while (!m_electrogramStream.fail())
125  {
126  m_electrogramStream >> gloCoord[0] >> gloCoord[1] >> gloCoord[2];
127  if (!m_electrogramStream.fail())
128  {
131  ::AllocateSharedPtr(dim, i, gloCoord[0],
132  gloCoord[1], gloCoord[2]);
133 
134  m_electrogramPoints.push_back(vert);
135  ++i;
136  }
137  }
138 
139  if (vComm->GetRank() == 0)
140  {
141  // Open output stream
142  m_outputStream.open(m_outputFile.c_str());
143  m_outputStream << "# Electrogram data for variables (:";
144 
145  for (i = 0; i < pFields.num_elements(); ++i)
146  {
147  m_outputStream << m_session->GetVariable(i) <<",";
148  }
149 
150  m_outputStream << ") at points:" << endl;
151 
152  for (i = 0; i < m_electrogramPoints.size(); ++i)
153  {
154  m_electrogramPoints[i]->GetCoords( gloCoord[0],
155  gloCoord[1],
156  gloCoord[2]);
157 
158  m_outputStream << "# \t" << i;
159  m_outputStream.width(8);
160  m_outputStream << gloCoord[0];
161  m_outputStream.width(8);
162  m_outputStream << gloCoord[1];
163  m_outputStream.width(8);
164  m_outputStream << gloCoord[2];
165  m_outputStream << endl;
166  }
167  }
168 
169  // Compute the distance function for each electrogram point
170  const unsigned int nq = pFields[0]->GetNpoints();
171  const unsigned int npts = m_electrogramPoints.size();
172  NekDouble px, py, pz;
176 
180 
181  Array<OneD, NekDouble> oneOverR(nq);
182  for (unsigned int i = 0; i < npts; ++i)
183  {
185  m_grad_R_y[i] = Array<OneD, NekDouble>(nq);
186  m_grad_R_z[i] = Array<OneD, NekDouble>(nq);
187 
188  // Compute 1/R
189  m_electrogramPoints[i]->GetCoords(px,py,pz);
190 
191  pFields[0]->GetCoords(x,y,z);
192 
193  Vmath::Sadd (nq, -px, x, 1, x, 1);
194  Vmath::Sadd (nq, -py, y, 1, y, 1);
195  Vmath::Sadd (nq, -pz, z, 1, z, 1);
196  Vmath::Vvtvvtp(nq, x, 1, x, 1, y, 1, y, 1, oneOverR, 1);
197  Vmath::Vvtvp (nq, z, 1, z, 1, oneOverR, 1, oneOverR, 1);
198  Vmath::Vsqrt (nq, oneOverR, 1, oneOverR, 1);
199  Vmath::Sdiv (nq, 1.0, oneOverR, 1, oneOverR, 1);
200 
201  // Compute grad 1/R
202  pFields[0]->PhysDeriv(oneOverR, m_grad_R_x[i], m_grad_R_y[i],
203  m_grad_R_z[i]);
204  }
205 
206  // Compute electrogram point for initial condition
207  v_Update(pFields, time);
208 }
209 
210 
211 /**
212  *
213  */
216  const NekDouble &time)
217 {
218  // Only output every m_outputFrequency.
219  if ((m_index++) % m_outputFrequency)
220  {
221  return;
222  }
223 
224  const unsigned int nq = pFields[0]->GetNpoints();
225  const unsigned int npoints = m_electrogramPoints.size();
226  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
227 
228  unsigned int i = 0;
229  Array<OneD, NekDouble> e(npoints);
230 
231  // Compute grad V
232  Array<OneD, NekDouble> grad_V_x(nq), grad_V_y(nq), grad_V_z(nq);
233  pFields[0]->PhysDeriv(pFields[0]->GetPhys(),
234  grad_V_x, grad_V_y, grad_V_z);
235 
236  for (i = 0; i < npoints; ++i)
237  {
238  // Multiply together
239  Array<OneD, NekDouble> output(nq);
240  Vmath::Vvtvvtp(nq, m_grad_R_x[i], 1, grad_V_x, 1, m_grad_R_y[i], 1,
241  grad_V_y, 1, output, 1);
242  Vmath::Vvtvp (nq, m_grad_R_z[i], 1, grad_V_z, 1, output, 1,
243  output, 1);
244 
245  e[i] = pFields[0]->Integral(output);
246  }
247 
248  // Exchange history data
249  // This could be improved to reduce communication but works for now
250  vComm->AllReduce(e, LibUtilities::ReduceSum);
251 
252  // Only the root process writes out electrogram data
253  if (vComm->GetRank() == 0)
254  {
255  m_outputStream.width(8);
256  m_outputStream << setprecision(6) << time;
257 
258  // Write data values point by point
259  for (i = 0; i < m_electrogramPoints.size(); ++i)
260  {
261  m_outputStream.width(25);
262  m_outputStream << setprecision(16) << e[i];
263  }
264  m_outputStream << endl;
265  }
266 }
267 
268 
269 /**
270  *
271  */
274  const NekDouble &time)
275 {
276  if (pFields[0]->GetComm()->GetRank() == 0)
277  {
278  m_outputStream.close();
279  }
280 }
281 
282 
283 /**
284  *
285  */
287 {
288  return true;
289 }
290 }
unsigned int m_index
Counts number of calls to update (number of timesteps)
std::string m_outputFile
Filename to output electrogram data to.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:161
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:394
Array< OneD, Array< OneD, NekDouble > > m_grad_R_y
Gradient of the radius from each electrogram point in y-direction.
std::stringstream m_electrogramStream
Point coordinate input string.
virtual void v_Finalise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
Finalise the electrogram filter and close output file.
std::ofstream m_outputStream
Output file stream for electrogram data.
virtual bool v_IsTimeDependent()
Filter is time-dependent and should be called at each time-step.
SpatialDomains::PointGeomVector m_electrogramPoints
List of electrogram points.
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:428
virtual void v_Update(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
Compute extracellular potential at egm points at current time.
STL namespace.
void Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/y.
Definition: Vmath.cpp:257
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
unsigned int m_outputFrequency
Number of timesteps between outputs.
boost::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
NekDouble Evaluate() const
Definition: Equation.h:102
static std::string npts
Definition: InputFld.cpp:43
double NekDouble
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.cpp:301
std::map< std::string, std::string > ParamMap
Definition: Filter.h:67
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:84
void Vvtvvtp(int n, const T *v, int incv, const T *w, int incw, const T *x, int incx, const T *y, int incy, T *z, int incz)
vvtvvtp (vector times vector plus vector times vector):
Definition: Vmath.cpp:523
Array< OneD, Array< OneD, NekDouble > > m_grad_R_z
Gradient of the radius from each electrogram point in z-direction.
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:42
virtual ~FilterElectrogram()
Electrogram filter destructor.
virtual void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
Initialises the electrogram filter and open output file.
boost::shared_ptr< PointGeom > PointGeomSharedPtr
Definition: Geometry.h:60
Array< OneD, Array< OneD, NekDouble > > m_grad_R_x
Gradient of the radius from each electrogram point in x-direction.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215