MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CubeMesh.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment.
4 ** Copyright (C) 2011 Upinder S. Bhalla. and NCBS
5 ** It is made available under the terms of the
6 ** GNU Lesser General Public License version 2.1
7 ** See the file COPYING.LIB for the full notice.
8 **********************************************************************/
9 
10 #include "header.h"
11 #include "SparseMatrix.h"
12 #include "ElementValueFinfo.h"
13 #include "Boundary.h"
14 #include "MeshEntry.h"
15 #include "VoxelJunction.h"
16 // #include "Stencil.h"
17 #include "ChemCompt.h"
18 #include "MeshCompt.h"
19 #include "CubeMesh.h"
20 #include "EndoMesh.h"
21 
22 const unsigned int CubeMesh::EMPTY = ~0;
23 const unsigned int CubeMesh::SURFACE = ~1;
24 const unsigned int CubeMesh::ABUTX = ~2;
25 const unsigned int CubeMesh::ABUTY = ~3;
26 const unsigned int CubeMesh::ABUTZ = ~4;
27 const unsigned int CubeMesh::MULTI = ~5;
28 
29 typedef pair< unsigned int, unsigned int > PII;
30 
32 {
34  // Field Definitions
37  "x0",
38  "X coord of one end",
41  );
43  "y0",
44  "Y coord of one end",
47  );
49  "z0",
50  "Z coord of one end",
53  );
55  "x1",
56  "X coord of other end",
59  );
61  "y1",
62  "Y coord of other end",
65  );
67  "z1",
68  "Z coord of other end",
71  );
72 
74  "dx",
75  "X size for mesh",
78  );
80  "dy",
81  "Y size for mesh",
84  );
86  "dz",
87  "Z size for mesh",
90  );
91 
93  "nx",
94  "Number of subdivisions in mesh in X",
97  );
99  "ny",
100  "Number of subdivisions in mesh in Y",
103  );
105  "nz",
106  "Number of subdivisions in mesh in Z",
109  );
110 
111  static ValueFinfo< CubeMesh, bool > isToroid(
112  "isToroid",
113  "Flag. True when the mesh should be toroidal, that is,"
114  "when going beyond the right face brings us around to the"
115  "left-most mesh entry, and so on. If we have nx, ny, nz"
116  "entries, this rule means that the coordinate (x, ny, z)"
117  "will map onto (x, 0, z). Similarly,"
118  "(-1, y, z) -> (nx-1, y, z)"
119  "Default is false",
122  );
123 
124  static ValueFinfo< CubeMesh, bool > preserveNumEntries(
125  "preserveNumEntries",
126  "Flag. When it is true, the numbers nx, ny, nz remain"
127  "unchanged when x0, x1, y0, y1, z0, z1 are altered. Thus"
128  "dx, dy, dz would change instead. When it is false, then"
129  "dx, dy, dz remain the same and nx, ny, nz are altered."
130  "Default is true",
133  );
134 
135  static ValueFinfo< CubeMesh, bool > alwaysDiffuse(
136  "alwaysDiffuse",
137  "Flag. When it is true, the mesh matches up sequential "
138  "mesh entries for diffusion and chmestry. This is regardless "
139  "of spatial location, and is guaranteed to set up at least "
140  "the home reaction system"
141  "Default is false",
144  );
145 
147  "coords",
148  "Set all the coords of the cuboid at once. Order is:"
149  "x0 y0 z0 x1 y1 z1 dx dy dz"
150  "When this is done, it recalculates the numEntries since "
151  "dx, dy and dz are given explicitly."
152  "As a special hack, you can leave out dx, dy and dz and use "
153  "a vector of size 6. In this case the operation assumes that "
154  "nx, ny and nz are to be preserved and dx, dy and dz will "
155  "be recalculated. ",
158  );
159 
161  "meshToSpace",
162  "Array in which each mesh entry stores spatial (cubic) index",
165  );
166 
168  "spaceToMesh",
169  "Array in which each space index (obtained by linearizing "
170  "the xyz coords) specifies which meshIndex is present."
171  "In many cases the index will store the EMPTY flag if there is"
172  "no mesh entry at that spatial location",
175  );
176 
178  "surface",
179  "Array specifying surface of arbitrary volume within the "
180  "CubeMesh. All entries must fall within the cuboid. "
181  "Each entry of the array is a spatial index obtained by "
182  "linearizing the ix, iy, iz coordinates within the cuboid. "
183  "So, each entry == ( iz * ny + iy ) * nx + ix"
184  "Note that the voxels listed on the surface are WITHIN the "
185  "volume of the CubeMesh object",
188  );
189 
191  // MsgDest Definitions
193 
194  static DestFinfo buildMesh( "buildMesh",
195  "Build cubical mesh for geom surface specified by Id, using"
196  "specified x y z coords as an inside point in mesh",
199  );
200 
202  // Field Elements
204 
205  static Finfo* cubeMeshFinfos[] = {
206  &isToroid, // Value
207  &preserveNumEntries, // Value
208  &alwaysDiffuse, // Value
209  &x0, // Value
210  &y0, // Value
211  &z0, // Value
212  &x1, // Value
213  &y1, // Value
214  &z1, // Value
215  &dx, // Value
216  &dy, // Value
217  &dz, // Value
218  &nx, // Value
219  &ny, // Value
220  &nz, // Value
221  &coords, // Value
222  &meshToSpace, // Value
223  &spaceToMesh, // Value
224  &surface, // Value
225  };
226 
227  static string doc[] =
228  {
229  "Name", "CubeMesh",
230  "Author", "Upi Bhalla",
231  "Description", "Chemical compartment with cuboid grid. "
232  "Defaults to a cube of size 10 microns, with mesh size "
233  "also 10 microns, so that there is just 1 cubic voxel. "
234  "These defaults are similar to that of a typical cell. "
235  "Can be configured to have different x,y,z dimensions and "
236  "also different dx,dy,dz voxel sizes. ",
237  };
238  static Dinfo< CubeMesh > dinfo;
239  static Cinfo cubeMeshCinfo (
240  "CubeMesh",
242  cubeMeshFinfos,
243  sizeof( cubeMeshFinfos ) / sizeof ( Finfo* ),
244  &dinfo,
245  doc,
246  sizeof(doc)/sizeof(string)
247  );
248 
249  return &cubeMeshCinfo;
250 }
251 
253 // Basic class Definitions
255 
257 
259 // Class stuff.
262  :
263  isToroid_( 0 ),
264  preserveNumEntries_( 1 ),
265  alwaysDiffuse_( false ),
266  x0_( 0.0 ),
267  y0_( 0.0 ),
268  z0_( 0.0 ),
269  x1_( 10e-6 ),
270  y1_( 10e-6 ),
271  z1_( 10e-6 ),
272  dx_( 10e-6 ),
273  dy_( 10e-6 ),
274  dz_( 10e-6 ),
275  nx_( 1 ),
276  ny_( 1 ),
277  nz_( 1 ),
278  m2s_( 1, 0 ),
279  s2m_( 1, 0 )
280 {
281  updateCoords();
282 }
283 
285 {
286  ;
287 }
288 
290 // Field assignment stuff
292 
293 // Swaps x0 and x1 if x0 > x1
294 void swapIfBackward( double& x0, double& x1 )
295 {
296  if ( x0 > x1 ) {
297  double temp = x0;
298  x0 = x1;
299  x1 = temp;
300  }
301 }
302 
304 {
305  unsigned int size = nx_ * ny_ * nz_;
306  if ( nx_ == 1 ) {
307  for ( unsigned int j = 0; j < ny_; ++j )
308  surface_.push_back( j );
309  for ( unsigned int j = size - ny_; j < size; ++j )
310  surface_.push_back( j );
311  for ( unsigned int i = 1; i < nz_ - 1; ++i )
312  surface_.push_back( i * ny_ );
313  for ( unsigned int i = 1; i < nz_ - 1; ++i )
314  surface_.push_back( ny_ - 1 + i * ny_ );
315  } else if ( ny_ == 1 ) {
316  for ( unsigned int k = 0; k < nx_; ++k )
317  surface_.push_back( k );
318  for ( unsigned int k = size - nx_; k < size; ++k )
319  surface_.push_back( k );
320  for ( unsigned int i = 1; i < nz_ - 1; ++i )
321  surface_.push_back( i * nx_ );
322  for ( unsigned int i = 1; i < nz_ - 1; ++i )
323  surface_.push_back( nx_ - 1 + i * nx_ );
324  } else if ( nz_ == 1 ) {
325  for ( unsigned int k = 0; k < nx_; ++k )
326  surface_.push_back( k );
327  for ( unsigned int k = size - nx_; k < size; ++k )
328  surface_.push_back( k );
329  for ( unsigned int j = 1; j < ny_ - 1; ++j )
330  surface_.push_back( j * nx_ );
331  for ( unsigned int j = 1; j < ny_ - 1; ++j )
332  surface_.push_back( j * nx_ + nx_ - 1 );
333  }
334  // Ah, C++ STL. Look on my works, ye mighty, and despair.
335  sort( surface_.begin(), surface_.end() );
336  surface_.erase( unique( surface_.begin(), surface_.end() ),
337  surface_.end() );
338 }
339 
340 void CubeMesh::fillThreeDimSurface() // Need to fix duplicate points.
341 {
342  unsigned int size = nx_ * ny_ * nz_;
343  // z == 0 plane
344  for ( unsigned int j = 0; j < ny_; ++j )
345  for ( unsigned int k = 0; k < nx_; ++k )
346  surface_.push_back( j * nx_ + k );
347  // z == nz_-1 plane
348  unsigned int offset = size - nx_ * ny_;
349  for ( unsigned int j = 0; j < ny_; ++j )
350  for ( unsigned int k = 0; k < nx_; ++k )
351  surface_.push_back( offset + j * nx_ + k );
352 
353  // y == 0 plane
354  for ( unsigned int i = 0; i < nz_; ++i )
355  for ( unsigned int k = 0; k < nx_; ++k )
356  surface_.push_back( i * nx_ * ny_ + k );
357  // y == ny_-1 plane
358  offset = nx_ * ( ny_ - 1 );
359  for ( unsigned int i = 0; i < nz_; ++i )
360  for ( unsigned int k = 0; k < nx_; ++k )
361  surface_.push_back( offset + i * nx_ * ny_ + k );
362 
363  // x == 0 plane
364  for ( unsigned int i = 0; i < nz_; ++i )
365  for ( unsigned int j = 0; j < ny_; ++j )
366  surface_.push_back( ( i * ny_ + j ) * nx_ );
367  // x == nx_-1 plane
368  offset = nx_ - 1;
369  for ( unsigned int i = 0; i < nz_; ++i )
370  for ( unsigned int j = 0; j < ny_; ++j )
371  surface_.push_back( offset + ( i * ny_ + j ) * nx_ );
372 
373  sort( surface_.begin(), surface_.end() );
374  surface_.erase( unique( surface_.begin(), surface_.end() ),
375  surface_.end() );
376 }
377 
385 {
386  swapIfBackward( x0_, x1_ );
387  swapIfBackward( y0_, y1_ );
388  swapIfBackward( z0_, z1_ );
389  if ( preserveNumEntries_ ) {
390  dx_ = ( x1_ - x0_ ) / nx_;
391  dy_ = ( y1_ - y0_ ) / ny_;
392  dz_ = ( z1_ - z0_ ) / nz_;
393  } else {
394  nx_ = round( (x1_ - x0_) / dx_ );
395  ny_ = round( (y1_ - y0_) / dy_ );
396  nz_ = round( (z1_ - z0_) / dz_ );
397 
398  if ( nx_ == 0 ) nx_ = 1;
399  if ( ny_ == 0 ) ny_ = 1;
400  if ( nz_ == 0 ) nz_ = 1;
401  }
402 
404  // will change for none-cube geometries.
405  unsigned int size = nx_ * ny_ * nz_;
406  m2s_.resize( size );
407  s2m_.resize( size );
408  for ( unsigned int i = 0; i < size; ++i ) {
409  m2s_[i] = s2m_[i] = i;
410  }
411 
412  // Fill out surface vector
413  surface_.resize( 0 );
414  /*
415  if ( numDims() == 0 ) {
416  surface_.push_back( 0 );
417  } else if ( numDims() == 1 ) {
418  surface_.push_back( 0 );
419  if ( size > 1 )
420  surface_.push_back( size - 1 );
421  } else if ( numDims() == 2 ) {
422  fillTwoDimSurface();
423  } else if ( numDims() == 3 ) {
424  fillThreeDimSurface();
425  }
426  */
428 
429  // volume_ = ( x1_ - x0_ ) * ( y1_ - y0_ ) * ( z1_ - z0_ );
430  assert( size >= 0 );
431 
432  buildStencil();
433 }
434 
435 void CubeMesh::setX0( double v )
436 {
437  x0_ = v;
438  updateCoords();
439 }
440 
441 double CubeMesh::getX0() const
442 {
443  return x0_;
444 }
445 
446 void CubeMesh::setY0( double v )
447 {
448  y0_ = v;
449  updateCoords();
450 }
451 
452 double CubeMesh::getY0() const
453 {
454  return y0_;
455 }
456 
457 void CubeMesh::setZ0( double v )
458 {
459  z0_ = v;
460  updateCoords();
461 }
462 
463 double CubeMesh::getZ0() const
464 {
465  return z0_;
466 }
467 
468 void CubeMesh::setX1( double v )
469 {
470  x1_ = v;
471  updateCoords();
472 }
473 
474 double CubeMesh::getX1() const
475 {
476  return x1_;
477 }
478 
479 void CubeMesh::setY1( double v )
480 {
481  y1_ = v;
482  updateCoords();
483 }
484 
485 double CubeMesh::getY1() const
486 {
487  return y1_;
488 }
489 
490 void CubeMesh::setZ1( double v )
491 {
492  z1_ = v;
493  updateCoords();
494 }
495 
496 double CubeMesh::getZ1() const
497 {
498  return z1_;
499 }
500 
501 void CubeMesh::setDx( double v )
502 {
503  dx_ = v;
504  updateCoords();
505 }
506 
507 double CubeMesh::getDx() const
508 {
509  return dx_;
510 }
511 
512 
513 void CubeMesh::setDy( double v )
514 {
515  dy_ = v;
516  updateCoords();
517 }
518 
519 double CubeMesh::getDy() const
520 {
521  return dy_;
522 }
523 
524 
525 void CubeMesh::setDz( double v )
526 {
527  dz_ = v;
528  updateCoords();
529 }
530 
531 double CubeMesh::getDz() const
532 {
533  return dz_;
534 }
535 
536 void CubeMesh::setNx( unsigned int v )
537 {
538  nx_ = v;
539  updateCoords();
540 }
541 
542 unsigned int CubeMesh::getNx() const
543 {
544  return nx_;
545 }
546 
547 
548 void CubeMesh::setNy( unsigned int v )
549 {
550  ny_ = v;
551  updateCoords();
552 }
553 
554 unsigned int CubeMesh::getNy() const
555 {
556  return ny_;
557 }
558 
559 void CubeMesh::setNz( unsigned int v )
560 {
561  nz_ = v;
562  updateCoords();
563 }
564 
565 unsigned int CubeMesh::getNz() const
566 {
567  return nz_;
568 }
569 
570 
571 void CubeMesh::setIsToroid( bool v )
572 {
573  isToroid_ = v;
574 }
575 
577 {
578  return isToroid_;
579 }
580 
582 {
584 }
585 
587 {
588  return preserveNumEntries_;
589 }
590 
592 {
593  alwaysDiffuse_ = v;
594 }
595 
597 {
598  // alwaysDiffuse is normally false.
599  return alwaysDiffuse_;
600 }
601 
602 void CubeMesh::innerSetCoords( const vector< double >& v)
603 {
604  if ( v.size() < 6 )
605  return;
606 
607  x0_ = v[0];
608  y0_ = v[1];
609  z0_ = v[2];
610 
611  x1_ = v[3];
612  y1_ = v[4];
613  z1_ = v[5];
614 
615  bool temp = preserveNumEntries_;
616  if ( v.size() >= 9 ) {
617  dx_ = v[6];
618  dy_ = v[7];
619  dz_ = v[8];
621  } else {
623  }
624  updateCoords();
625  preserveNumEntries_ = temp;
626 
627 }
628 
629 void CubeMesh::setCoords( const Eref& e, vector< double > v)
630 {
631  // double oldVol = getMeshEntryVolume( 0 );
632  innerSetCoords( v );
633  ChemCompt::voxelVolOut()->send( e, vGetVoxelVolume() );
634 }
635 
636 vector< double > CubeMesh::getCoords( const Eref& e ) const
637 {
638  vector< double > ret( 9 );
639 
640  ret[0] = x0_;
641  ret[1] = y0_;
642  ret[2] = z0_;
643 
644  ret[3] = x1_;
645  ret[4] = y1_;
646  ret[5] = z1_;
647 
648  ret[6] = dx_;
649  ret[7] = dy_;
650  ret[8] = dz_;
651 
652  return ret;
653 }
654 
655 void CubeMesh::setMeshToSpace( vector< unsigned int > v )
656 {
657  m2s_ = v;
659 }
660 
661 vector< unsigned int > CubeMesh::getMeshToSpace() const
662 {
663  return m2s_;
664 }
665 
666 void CubeMesh::setSpaceToMesh( vector< unsigned int > v )
667 {
668  s2m_ = v;
670 }
671 
672 vector< unsigned int > CubeMesh::getSpaceToMesh() const
673 {
674  return s2m_;
675 }
676 
677 void CubeMesh::setSurface( vector< unsigned int > v )
678 {
679  surface_ = v;
680 }
681 
682 vector< unsigned int > CubeMesh::getSurface() const
683 {
684  return surface_;
685 }
686 
687 unsigned int CubeMesh::innerGetDimensions() const
688 {
689  return 3;
690 }
691 
692 
694 // DestFinfos
696 
697 void CubeMesh::buildMesh( Id geom, double x, double y, double z )
698 {
699  ;
700 }
701 
708  double volume, unsigned int numEntries )
709 {
710  double approxN = numEntries;
711  approxN = pow( approxN, 1.0 / 3.0 );
712  unsigned int smaller = floor( approxN );
713  unsigned int bigger = ceil( approxN );
714  unsigned int numSide;
715  if ( smaller != bigger ) {
716  numSide = smaller;
717  } else {
718  unsigned int smallerVol = smaller * smaller * smaller;
719  unsigned int biggerVol = bigger * bigger * bigger;
720  if ( numEntries - smallerVol < biggerVol - numEntries )
721  numSide = smaller;
722  else
723  numSide = bigger;
724  }
725  double side = pow( volume, 1.0 / 3.0 );
726  vector< double > coords( 9, side );
727  coords[0] = coords[1] = coords[2] = 0;
728  coords[6] = coords[7] = coords[8] = side / numSide;
729  nx_ = ny_ = nz_ = numSide;
730  setCoords( e, coords );
731 }
732 
735  const SrcFinfo2< unsigned int, vector< double > >* meshStatsFinfo )
736 {
737  vector< double > meshVolumes( 1, dx_ * dy_ * dz_ );
738  meshStatsFinfo->send( e, nx_ * ny_ * nz_, meshVolumes);
739 }
740 
744  const Eref& e,
745  unsigned int numNodes, unsigned int numThreads )
746 {
747  /*
748  unsigned int numEntries = nx_ * ny_ * nz_ ;
749  vector< double > vols( numEntries, dx_ * dy_ * dz_ );
750  vector< unsigned int > localEntries( numEntries );
751  vector< vector< unsigned int > > outgoingEntries;
752  vector< vector< unsigned int > > incomingEntries;
753  double oldvol = getMeshEntryVolume( 0 );
754  meshSplit()->send( e,
755  oldvol,
756  vols, localEntries,
757  outgoingEntries, incomingEntries );
758  */
759 }
760 
762 {
763  return fabs( (x1_ - x0_) * (y1_ - y0_) * (z1_ - z0_) );
764 }
765 
766 
768 // FieldElement assignment stuff for MeshEntries
770 
772 unsigned int CubeMesh::getMeshType( unsigned int fid ) const
773 {
774  return CUBOID;
775 }
776 
778 unsigned int CubeMesh::getMeshDimensions( unsigned int fid ) const
779 {
780  return 3;
781 }
782 
784 double CubeMesh::getMeshEntryVolume( unsigned int fid ) const
785 {
786  return dx_ * dy_ * dz_;
787 }
788 
790 // for diffusively coupled voxels from other solvers.
791 double CubeMesh::extendedMeshEntryVolume( unsigned int fid ) const
792 {
793  if ( fid >= m2s_.size() ) {
794  return MeshCompt::extendedMeshEntryVolume( fid - m2s_.size() );
795  }
796  return dx_ * dy_ * dz_;
797 }
798 
801 vector< double > CubeMesh::getCoordinates( unsigned int fid ) const
802 {
803  assert( fid < m2s_.size() );
804  unsigned int spaceIndex = m2s_[fid];
805 
806  unsigned int ix = spaceIndex % nx_;
807  unsigned int iy = (spaceIndex / nx_) % ny_;
808  unsigned int iz = (spaceIndex / ( nx_ * ny_ )) % nz_;
809 
810  vector< double > ret( 6 );
811  ret[0] = x0_ + ix * dx_;
812  ret[1] = y0_ + iy * dy_;
813  ret[2] = z0_ + iz * dz_;
814 
815  ret[3] = x0_ + ix * dx_ + dx_;
816  ret[4] = y0_ + iy * dy_ + dx_;
817  ret[5] = z0_ + iz * dz_ + dx_;
818 
819  return ret;
820 }
821 
822 unsigned int CubeMesh::neighbor( unsigned int spaceIndex,
823  int dx, int dy, int dz ) const
824 {
825  int ix = spaceIndex % nx_;
826  int iy = (spaceIndex / nx_) % ny_;
827  int iz = (spaceIndex / ( nx_ * ny_ )) % nz_;
828 
829  ix += dx;
830  iy += dy;
831  iz += dz;
832 
833  if ( ix < 0 || ix >= static_cast< int >( nx_ ) )
834  return EMPTY;
835  if ( iy < 0 || iy >= static_cast< int >( ny_ ) )
836  return EMPTY;
837  if ( iz < 0 || iz >= static_cast< int >( nz_ ) )
838  return EMPTY;
839 
840  unsigned int nIndex = ( ( iz * ny_ ) + iy ) * nx_ + ix;
841 
842  return s2m_[nIndex];
843 }
844 
846 vector< double > CubeMesh::getDiffusionArea( unsigned int fid ) const
847 {
848  assert( fid < m2s_.size() );
849 
850  vector< double > ret;
851  unsigned int spaceIndex = m2s_[fid];
852 
853  unsigned int nIndex = neighbor( spaceIndex, 0, 0, 1 );
854  if ( nIndex != EMPTY )
855  ret.push_back( dx_ * dy_ );
856 
857  nIndex = neighbor( spaceIndex, 0, 0, -1 );
858  if ( nIndex != EMPTY )
859  ret.push_back( dx_ * dy_ );
860 
861  nIndex = neighbor( spaceIndex, 0, 1, 0 );
862  if ( nIndex != EMPTY )
863  ret.push_back( dz_ * dx_ );
864 
865  nIndex = neighbor( spaceIndex, 0, -1, 0 );
866  if ( nIndex != EMPTY )
867  ret.push_back( dz_ * dx_ );
868 
869  nIndex = neighbor( spaceIndex, 1, 0, 0 );
870  if ( nIndex != EMPTY )
871  ret.push_back( dy_ * dz_ );
872 
873  nIndex = neighbor( spaceIndex, -1, 0, 0 );
874  if ( nIndex != EMPTY )
875  ret.push_back( dy_ * dz_ );
876 
877  return ret;
878 }
879 
881 vector< double > CubeMesh::getDiffusionScaling( unsigned int fid ) const
882 {
883  return vector< double >( 6, 1.0 );
884 }
885 
887 
891 unsigned int CubeMesh::innerGetNumEntries() const
892 {
893  return m2s_.size();
894 }
895 
899 void CubeMesh::innerSetNumEntries( unsigned int n )
900 {
901  cout << "Warning: CubeMesh::innerSetNumEntries is readonly.\n";
902 }
903 
904 // We assume this is linear diffusion for now. Fails for 2 or 3-D diffusion
905 vector< unsigned int > CubeMesh::getParentVoxel() const
906 {
907  unsigned int numEntries = innerGetNumEntries();
908  vector< unsigned int > ret( numEntries );
909  if ( numEntries > 0 )
910  ret[0] = static_cast< unsigned int >( -1 );
911  for (unsigned int i = 1; i < numEntries; ++i )
912  ret[i] = i-1;
913 
914  return ret;
915 }
916 
917 const vector< double >& CubeMesh::vGetVoxelVolume() const
918 {
919  static vector< double > vol;
920  vol.clear();
921  vol.resize( nx_ * ny_ * nz_, dx_ * dy_ * dz_ );
922  return vol;
923 }
924 
925 const vector< double >& CubeMesh::vGetVoxelMidpoint() const
926 {
927  static vector< double > midpoint;
928  midpoint.resize( m2s_.size() * 3 );
929  for ( unsigned int i = 0; i < m2s_.size(); ++i ) // x coords. Lowest.
930  midpoint[i] = x0_ + ( 0.5 + (m2s_[i] % nx_ ) ) * dx_;
931  for ( unsigned int i = 0; i < m2s_.size(); ++i ) { // y coords. Middle.
932  unsigned int k = i + m2s_.size();
933  midpoint[k] = y0_ + ( 0.5 + ( (m2s_[i] / nx_) % ny_ ) ) * dy_;
934  }
935  for ( unsigned int i = 0; i < m2s_.size(); ++i ) { // z coords. Top.
936  unsigned int k = i + m2s_.size() * 2;
937  midpoint[k] = z0_ + ( 0.5 + ( m2s_[i] / ( nx_ * ny_ ) ) ) * dz_;
938  }
939  return midpoint;
940 }
941 
942 const vector< double >& CubeMesh::getVoxelArea() const
943 {
944  static vector< double > area;
945  if ( nx_ * ny_ == 1 )
946  area.resize( nz_, dx_ * dy_ );
947  else if ( nx_ * nz_ == 1 )
948  area.resize( ny_, dx_ * dz_ );
949  else if ( ny_ * nz_ == 1 )
950  area.resize( nx_, dy_ * dz_ );
951  else
952  area.resize( nx_, dy_ * dz_ ); // Just put in a number.
953  assert( area.size() == nx_ * ny_ * nz_ );
954  return area;
955 }
956 
957 const vector< double >& CubeMesh::getVoxelLength() const
958 {
959  static vector< double > length;
960  if ( dx_ > dy_ && dx_ > dz_ )
961  length.assign( innerGetNumEntries(), dx_ );
962  else if ( dy_ > dz_ )
963  length.assign( innerGetNumEntries(), dy_ );
964  else
965  length.assign( innerGetNumEntries(), dz_ );
966  return length;
967 }
968 
970 {
971  // Leave x0,y0.z0 and nx,ny,nz the same. Do NOT update any rates.
972  double oldvol = vGetEntireVolume();
973  double linscale = pow( vol / oldvol , 1.0 / 3.0 );
974  dx_ *= linscale;
975  dy_ *= linscale;
976  dz_ *= linscale;
977  x1_ = x0_ + dx_;
978  y1_ = y0_ + dy_;
979  z1_ = z0_ + dz_;
980 
981  return true;
982 }
983 
985 
986 bool CubeMesh::isInsideCuboid( double x, double y, double z ) const
987 {
988  return ( x >= x0_ && x < x1_ && y >= y0_ && y < y1_ &&
989  z >= z0_ && z < z1_ );
990 }
991 
992 bool CubeMesh::isInsideSpheroid( double x, double y, double z ) const
993 {
994  double cx = ( x0_ + x1_ ) / 2.0;
995  double cy = ( y0_ + y1_ ) / 2.0;
996  double cz = ( z0_ + z1_ ) / 2.0;
997 
998  double rx = ( x - cx ) / fabs( x1_ - x0_ ) / 2.0;
999  double ry = ( y - cy ) / fabs( y1_ - y0_ ) / 2.0;
1000  double rz = ( z - cz ) / fabs( z1_ - z0_ ) / 2.0;
1001 
1002  return ( ( rx * rx + ry * ry + rz * rz ) < 1.0 );
1003 }
1004 
1006 {
1007  static const unsigned int flag = EMPTY;
1008  unsigned int num = 0;
1009  unsigned int q = 0;
1010  m2s_.clear();
1011  s2m_.resize( nx_ * ny_ * nz_, flag );
1012  for( unsigned int k = 0; k < nz_; ++k ) {
1013  double z = k * dz_ + z0_;
1014  for( unsigned int j = 0; j < ny_; ++j ) {
1015  double y = j * dy_ + y0_;
1016  for( unsigned int i = 0; i < nx_; ++i ) {
1017  double x = i * dx_ + x0_;
1018  if ( isInsideCuboid( x, y, z ) ) {
1019  s2m_[q] = num;
1020  m2s_.push_back( q );
1021  ++num;
1022  } else {
1023  s2m_[q] = flag;
1024  }
1025  ++q;
1026  }
1027  }
1028  }
1029  assert( m2s_.size() == num );
1030 }
1031 
1032 // Reads off s2m to build m2s.
1034 {
1035  m2s_.clear();
1036  assert( s2m_.size() == nx_ * ny_ * nz_ );
1037  for ( unsigned int i = 0; i < s2m_.size(); ++i ) {
1038  if ( s2m_[i] != EMPTY ) {
1039  m2s_.push_back( i );
1040  assert( m2s_.size() == s2m_[i] + 1 );
1041  }
1042  }
1043  buildStencil();
1044 }
1045 
1047 {
1048  s2m_.clear();
1049  s2m_.resize( nx_ * ny_ * nz_, EMPTY );
1050  for ( unsigned int i = 0; i < m2s_.size(); ++i ) {
1051  s2m_[ m2s_[i] ] = i;
1052  }
1053  buildStencil();
1054 }
1055 
1056 // This is a general version of the function, just relies on the
1057 // contents of the s2m_ and m2s_ vectors to do its job.
1058 // Assumes that entire volume is bounded by nx_, ny_, nz.
1059 
1061 {
1062  static const unsigned int flag = EMPTY;
1063 
1064 
1065  // fillSpaceToMeshLookup();
1066  unsigned int num = m2s_.size();
1067  setStencilSize( num, num );
1068  for ( unsigned int i = 0; i < num; ++i ) {
1069  unsigned int q = m2s_[i];
1070  unsigned int ix = q % nx_;
1071  unsigned int iy = ( q / nx_ ) % ny_;
1072  unsigned int iz = ( q / ( nx_ * ny_ ) ) % nz_;
1073  vector< double > entry;
1074  vector< unsigned int > colIndex;
1075  vector< Ecol > e;
1076 
1077  if ( ix > 0 && s2m_[q-1] != flag ) {
1078  e.push_back( Ecol( dy_ * dz_ / dx_, s2m_[q-1] ) );
1079  }
1080  if ( ( ix < nx_ - 1 ) && s2m_[q+1] != flag ) {
1081  e.push_back( Ecol( dy_ * dz_ / dx_, s2m_[q+1] ) );
1082  }
1083  if ( iy > 0 && s2m_[ q-nx_ ] != flag ) {
1084  assert( q >= nx_ );
1085  e.push_back( Ecol( dx_ * dz_ / dy_, s2m_[q-nx_] ) );
1086  }
1087  if ( iy < ny_ - 1 && s2m_[ q+nx_ ] != flag ) {
1088  assert( q+nx_ < s2m_.size() );
1089  e.push_back( Ecol( dx_ * dz_ / dy_, s2m_[q+nx_] ) );
1090  }
1091  if ( iz > 0 && s2m_[ q - nx_*ny_ ] != flag ) {
1092  assert( q >= nx_ * ny_ );
1093  e.push_back( Ecol( dx_ * dy_ / dz_, s2m_[q - nx_ * ny_] ) );
1094  }
1095  if ( iz < nz_ - 1 && s2m_[ q + nx_*ny_ ] ) {
1096  assert( q+nx_ < s2m_.size() );
1097  e.push_back( Ecol( dx_ * dy_ / dz_, s2m_[q + nx_ * ny_] ) );
1098  }
1099  sort( e.begin(), e.end() );
1100  for ( vector< Ecol >::iterator j = e.begin(); j != e.end(); ++j ) {
1101  entry.push_back( j->e_ );
1102  colIndex.push_back( j->col_ );
1103  }
1104  addRow( i, entry, colIndex );
1105  }
1107 }
1108 
1110 
1111 const vector< unsigned int >& CubeMesh::surface() const
1112 {
1113  return surface_;
1114 }
1115 
1116 // For now: Just brute force through the surface list.
1117 // Surface list applies only if 2 or 3 D.
1119  vector< VoxelJunction >& ret ) const
1120 {
1121  const CubeMesh* cm = dynamic_cast< const CubeMesh* >( other );
1122 
1123  if ( cm ) {
1124  if ( alwaysDiffuse_ )
1125  matchAllEntries( cm, ret );
1126  else
1127  matchCubeMeshEntries( cm, ret );
1128  /*
1129  if ( compareMeshSpacing( cm ) == 0 ) { // Equal spacing.
1130  matchSameSpacing( cm, ret );
1131  } else if ( compareMeshSpacing( cm ) == -1 ) { // self is finer
1132  cout << "Warning:CubeMesh::matchMeshEntries: cannot yet handle unequal meshes\n";
1133  } else { // other is finer.
1134  cout << "Warning:CubeMesh::matchMeshEntries: cannot yet handle unequal meshes\n";
1135  }
1136  */
1137  return;
1138  }
1139  const EndoMesh* em = dynamic_cast< const EndoMesh* >( other );
1140  if ( em ) {
1141  em->matchMeshEntries( this, ret );
1142  flipRet( ret );
1143  return;
1144  }
1145  cout << "Warning:CubeMesh::matchMeshEntries: cannot yet handle Neuro or Cyl meshes.\n";
1146 }
1147 
1148 unsigned int CubeMesh::numDims() const
1149 {
1150  return ( ( nx_ > 1 ) + ( ny_ > 1 ) + ( nz_ > 1 ) );
1151 }
1152 
1153 
1154 void CubeMesh::indexToSpace( unsigned int index,
1155  double& x, double& y, double& z ) const
1156 {
1157  assert ( index < nx_ * ny_ * nz_ );
1158 
1159  // index = m2s_[index];
1160  unsigned int ix = index % nx_;
1161  index /= nx_;
1162  unsigned int iy = index % ny_;
1163  index /= ny_;
1164  unsigned int iz = index % nz_;
1165 
1166  x = x0_ + ix * dx_ + dx_ * 0.5;
1167  y = y0_ + iy * dy_ + dy_ * 0.5;
1168  z = z0_ + iz * dz_ + dz_ * 0.5;
1169 }
1170 
1171 unsigned int CubeMesh::spaceToIndex( double x, double y, double z ) const
1172 {
1173  if ( x > x0_ && x < x1_ && y > y0_ && y < y1_ && z > z0_ && z < z1_ )
1174  {
1175  unsigned int ix = ( x - x0_ ) / dx_;
1176  unsigned int iy = ( y - y0_ ) / dy_;
1177  unsigned int iz = ( z - z0_ ) / dz_;
1178  unsigned int index = ( iz * ny_ + iy ) * nx_ + ix;
1179  unsigned int innerIndex = s2m_[ index ];
1180  return innerIndex;
1181  }
1182  return EMPTY;
1183 }
1184 
1185 double CubeMesh::nearest( double x, double y, double z,
1186  unsigned int& index ) const
1187 {
1188  if ( x > x0_ && x < x1_ && y > y0_ && y < y1_ && z > z0_ && z < z1_ )
1189  {
1190  unsigned int ix = ( x - x0_ ) / dx_;
1191  unsigned int iy = ( y - y0_ ) / dy_;
1192  unsigned int iz = ( z - z0_ ) / dz_;
1193  index = ( iz * ny_ + iy ) * nx_ + ix;
1194  unsigned int innerIndex = s2m_[ index ];
1195  if ( innerIndex != EMPTY ) { // Inside filled volume
1196  index = innerIndex;
1197  double tx = x0_ + ix * dx_ + dx_ * 0.5;
1198  double ty = y0_ + iy * dy_ + dy_ * 0.5;
1199  double tz = z0_ + iz * dz_ + dz_ * 0.5;
1200  return distance( x - tx, y - ty, z - tz );
1201  } else { // Outside volume. Look over surface for nearest.
1202  double rmin = 1e99;
1203  for ( vector< unsigned int >::const_iterator
1204  i = surface_.begin(); i != surface_.end(); ++i )
1205  {
1206  double tx, ty, tz;
1207  indexToSpace( *i, tx, ty, tz );
1208  double r = distance( tx - x, ty - y, tz - z );
1209  if ( rmin > r ) {
1210  rmin = r;
1211  index = *i;
1212  }
1213  }
1214  return -rmin; // Negative distance indicates xyz is outside vol
1215  }
1216  }
1217  // Should really figure out nearest corner anyway.
1218  index = 0;
1219  return -1.0;
1220 }
1221 
1222 int CubeMesh::compareMeshSpacing( const CubeMesh* other ) const
1223 {
1224  if ( doubleApprox( dx_, other->dx_ ) &&
1225  doubleApprox( dy_, other->dy_ ) &&
1226  doubleApprox( dz_, other->dz_ ) )
1227  return 0; // equal
1228 
1229  if ( dx_ >= other->dx_ &&
1230  dy_ >= other->dy_ &&
1231  dz_ >= other->dz_ )
1232  return 1; // bigger
1233 
1234  if ( dx_ <= other->dx_ &&
1235  dy_ <= other->dy_ &&
1236  dz_ <= other->dz_ )
1237  return -1; // smaller than other.
1238 
1239 
1240  cout << "Warning: CubeMesh::compareMeshSpacing: inconsistent spacing\n";
1241  return 0;
1242 }
1243 
1245  double& xmin, double &xmax,
1246  double& ymin, double &ymax,
1247  double& zmin, double &zmax )
1248  const
1249 {
1250  const double meshSlop = 0.2;
1251  xmin = ( x0_ > other->x0_ ) ? x0_ : other->x0_;
1252  xmax = ( x1_ < other->x1_ ) ? x1_ : other->x1_;
1253  ymin = ( y0_ > other->y0_ ) ? y0_ : other->y0_;
1254  ymax = ( y1_ < other->y1_ ) ? y1_ : other->y1_;
1255  zmin = ( z0_ > other->z0_ ) ? z0_ : other->z0_;
1256  zmax = ( z1_ < other->z1_ ) ? z1_ : other->z1_;
1257  // Align to coarser mesh
1258  double temp = ( xmin - x0_) / dx_;
1259  if ( temp - floor( temp ) > meshSlop )
1260  xmin = floor( temp ) * dx_;
1261  temp = ( ymin - y0_) / dy_;
1262  if ( temp - floor( temp ) > meshSlop )
1263  ymin = floor( temp ) * dy_;
1264  temp = ( zmin - z0_) / dz_;
1265  if ( temp - floor( temp ) > meshSlop )
1266  zmin = floor( temp ) * dz_;
1267 
1268  // Provide 1 voxel padding all around.
1269  xmin -= dx_;
1270  xmax += dx_;
1271  ymin -= dy_;
1272  ymax += dy_;
1273  zmin -= dz_;
1274  zmax += dz_;
1275  swapIfBackward( xmin, xmax );
1276  swapIfBackward( ymin, ymax );
1277  swapIfBackward( zmin, zmax );
1278 }
1279 
1294 void setAbut( PII& voxel, unsigned int meshIndex, unsigned int axis )
1295 {
1296  if ( voxel.second == CubeMesh::SURFACE ) // Don't touch surface voxels.
1297  return;
1298  if ( voxel.second == CubeMesh::EMPTY )
1299  voxel = PII( meshIndex, axis );
1300  else // 1 or more indices are already here.
1301  voxel.second = CubeMesh::MULTI;
1302 }
1303 
1305  vector< PII >& intersect,
1306  unsigned int ix, unsigned int iy, unsigned int iz,
1307  unsigned int nx, unsigned int ny, unsigned int nz,
1308  unsigned int meshIndex )
1309 {
1310  assert( ix < nx && iy < ny && iz < nz );
1311  unsigned int index = ( iz * ny + iy ) * nx + ix;
1312  assert( index < intersect.size() );
1313  intersect[index] = PII( meshIndex, CubeMesh::SURFACE );
1314  if ( ix > 0 )
1315  setAbut( intersect[ (iz*ny + iy) * nx + ix-1 ], meshIndex,
1316  CubeMesh::ABUTX );
1317  if ( ix + 1 < nx )
1318  setAbut( intersect[ (iz*ny + iy) * nx + ix+1 ], meshIndex,
1319  CubeMesh::ABUTX );
1320 
1321  if ( iy > 0 )
1322  setAbut( intersect[ ( iz*ny + iy-1 ) * nx + ix ], meshIndex,
1323  CubeMesh::ABUTY);
1324  if ( iy + 1 < ny )
1325  setAbut( intersect[ ( iz*ny + iy+1 ) * nx + ix ], meshIndex,
1326  CubeMesh::ABUTY);
1327 
1328  if ( iz > 0 )
1329  setAbut( intersect[ ( (iz-1)*ny + iy ) * nx + ix ], meshIndex,
1330  CubeMesh::ABUTZ);
1331  if ( iz + 1 < nz )
1332  setAbut( intersect[ ( (iz+1)*ny + iy ) * nx + ix ], meshIndex,
1333  CubeMesh::ABUTZ);
1334 }
1335 
1336 
1349  const vector< PII >& intersect,
1350  unsigned int ix, unsigned int iy, unsigned int iz,
1351  unsigned int nx, unsigned int ny, unsigned int nz,
1352  unsigned int meshIndex,
1353  vector< VoxelJunction >& ret
1354  )
1355 {
1356  unsigned int index = ( iz * ny + iy ) * nx + ix;
1357  unsigned int localFlag = intersect[index].second;
1358 
1359  if ( localFlag == CubeMesh::EMPTY || localFlag == CubeMesh::SURFACE )
1360  return; // Nothing to put into the ret vector
1361  if ( localFlag == CubeMesh::ABUTX ) {
1362  ret.push_back(
1363  VoxelJunction( intersect[index].first, meshIndex, 0 ));
1364  } else if ( localFlag == CubeMesh::ABUTY ) {
1365  ret.push_back(
1366  VoxelJunction( intersect[index].first, meshIndex, 1 ));
1367  } else if ( localFlag == CubeMesh::ABUTZ ) {
1368  ret.push_back(
1369  VoxelJunction( intersect[index].first, meshIndex, 2 ));
1370  } else if ( localFlag == CubeMesh::MULTI ) { // go through all 6 cases.
1371  if ( ix > 0 ) {
1372  index = ( iz * ny + iy ) * nx + ix - 1;
1373  if ( intersect[index].second == CubeMesh::SURFACE )
1374  ret.push_back(
1375  VoxelJunction( intersect[index].first, meshIndex, 0 ));
1376  }
1377  if ( ix + 1 < nx ) {
1378  index = ( iz * ny + iy ) * nx + ix + 1;
1379  if ( intersect[index].second == CubeMesh::SURFACE )
1380  ret.push_back(
1381  VoxelJunction( intersect[index].first, meshIndex, 0 ));
1382  }
1383  if ( iy > 0 ) {
1384  index = ( iz * ny + iy -1 ) * nx + ix;
1385  if ( intersect[index].second == CubeMesh::SURFACE )
1386  ret.push_back(
1387  VoxelJunction( intersect[index].first, meshIndex, 1 ));
1388  }
1389  if ( iy + 1 < ny ) {
1390  index = ( iz * ny + iy + 1 ) * nx + ix;
1391  if ( intersect[index].second == CubeMesh::SURFACE )
1392  ret.push_back(
1393  VoxelJunction( intersect[index].first, meshIndex, 1 ));
1394  }
1395  if ( iz > 0 ) {
1396  index = ( (iz-1) * ny + iy ) * nx + ix;
1397  if ( intersect[index].second == CubeMesh::SURFACE )
1398  ret.push_back(
1399  VoxelJunction( intersect[index].first, meshIndex, 2 ));
1400  }
1401  if ( iz + 1 < nz ) {
1402  index = ( (iz+1) * ny + iy ) * nx + ix;
1403  if ( intersect[index].second == CubeMesh::SURFACE )
1404  ret.push_back(
1405  VoxelJunction( intersect[index].first, meshIndex, 2 ));
1406  }
1407  }
1408 }
1409 
1410 void CubeMesh::assignVoxels( vector< PII >& intersect,
1411  double xmin, double xmax,
1412  double ymin, double ymax,
1413  double zmin, double zmax
1414  ) const
1415 {
1416  unsigned int nx = 0.5 + ( xmax - xmin ) / dx_;
1417  unsigned int ny = 0.5 + ( ymax - ymin ) / dy_;
1418  unsigned int nz = 0.5 + ( zmax - zmin ) / dz_;
1419  // offset terms for nx, ny, nz from coord system for coarser grid.
1420  // Note that these can go negative if the intersect grid goes past
1421  // the coarse grid.
1422  int ox = round( ( xmin - x0_ ) / dx_ );
1423  int oy = round( ( ymin - y0_ ) / dy_ );
1424  int oz = round( ( zmin - z0_ ) / dz_ );
1425 
1426  // Scan through mesh surface using coarser grid, assign cuboid voxels
1427  for ( vector< unsigned int >::const_iterator i = surface_.begin();
1428  i != surface_.end(); ++i ) {
1429  unsigned int index = *i;
1430  double x, y, z;
1431  indexToSpace( index, x, y, z );
1432  if ( x >= xmin && x <= xmax && y >= ymin && y <= ymax &&
1433  z >= zmin && z <= zmax ) {
1434  int ix = index % nx_ - ox;
1435  assert( ix >= 0 );
1436  unsigned int uix = ix;
1437  index /= nx_;
1438  int iy = index % ny_ - oy;
1439  assert( iy >= 0 );
1440  unsigned int uiy = iy;
1441  index /= ny_;
1442  int iz = index % nz_ - oz;
1443  assert( iz >= 0 );
1444  unsigned int uiz = iz;
1445  unsigned int meshIndex = s2m_[ *i ];
1446 
1447  setIntersectVoxel( intersect, uix, uiy, uiz, nx, ny, nz,
1448  meshIndex );
1449  }
1450  }
1451 }
1452 
1454  vector< VoxelJunction >& ret ) const
1455 {
1456  // Flip meshes if the current grid is finer.
1457  // There are still problems here because a finer grid will end
1458  // up with 2 levels deep defined as being abutting.
1459  if ( compareMeshSpacing( other ) == -1 ) {
1460  other->matchMeshEntries( this, ret );
1461  flipRet( ret );
1462  return;
1463  }
1464  ret.resize( 0 );
1465  // Define intersecting cuboid
1466  double xmin, xmax, ymin, ymax, zmin, zmax;
1467  defineIntersection( other, xmin, xmax, ymin, ymax, zmin, zmax );
1468 
1469  // Allocate intersecting cuboid
1470  unsigned int nx = 0.5 + ( xmax - xmin ) / dx_;
1471  unsigned int ny = 0.5 + ( ymax - ymin ) / dy_;
1472  unsigned int nz = 0.5 + ( zmax - zmin ) / dz_;
1473  vector< PII > intersect( nx * ny * nz, PII( EMPTY, EMPTY ) );
1474  assignVoxels( intersect, xmin, xmax, ymin, ymax, zmin, zmax );
1475 
1476  // Scan through finer mesh surface, check for occupied voxels.
1477  for ( vector< unsigned int >::const_iterator i =
1478  other->surface_.begin();
1479  i != other->surface_.end(); ++i ) {
1480  double x, y, z;
1481  other->indexToSpace( *i, x, y, z );
1482  if ( x >= xmin && x <= xmax && y >= ymin && y <= ymax &&
1483  z >= zmin && z <= zmax ) {
1484  unsigned int ix = ( x - xmin ) / dx_;
1485  unsigned int iy = ( y - ymin ) / dy_;
1486  unsigned int iz = ( z - zmin ) / dz_;
1487  unsigned int meshIndex = other->s2m_[ *i ];
1488  checkAbut( intersect, ix, iy, iz, nx, ny, nz, meshIndex, ret );
1489  }
1490  }
1491 
1492  // Scan through the VoxelJunctions and populate their diffScale field
1493  setDiffScale( other, ret );
1494  // Scan through the VoxelJunctions and populate their volume field
1495  setJunctionVol( other, ret );
1496  sort( ret.begin(), ret.end() );
1497 }
1498 
1504  vector< VoxelJunction >& ret ) const
1505 {
1506  ret.clear();
1507  unsigned int min = m2s_.size();
1508  if ( min > other->m2s_.size() )
1509  min = other->m2s_.size();
1510  ret.resize( min );
1511  for ( unsigned int i = 0; i < min; ++i ) {
1512  ret[i] = VoxelJunction( i, i );
1513  }
1514 }
1515 
1517  vector< VoxelJunction >& ret ) const
1518 {
1519  other->matchMeshEntries( this, ret );
1520  flipRet( ret );
1521 }
1522 
1524  vector< VoxelJunction >& ret ) const
1525 {
1526 
1527  for ( vector< VoxelJunction >::iterator i = ret.begin();
1528  i != ret.end(); ++i )
1529  {
1530  if ( doubleEq( i->diffScale, 0 ) ) { // Junction across x plane
1531  double selfXA = dy_ * dz_;
1532  double otherXA = other->dy_ * other->dz_;
1533  if ( selfXA <= otherXA )
1534  i->diffScale = 2 * selfXA / ( dx_ + other->dx_ );
1535  else
1536  i->diffScale = 2 * otherXA / ( dx_ + other->dx_ );
1537  } else if ( doubleEq( i->diffScale, 1 ) ) { // across y plane
1538  double selfXA = dx_ * dz_;
1539  double otherXA = other->dx_ * other->dz_;
1540  if ( selfXA <= otherXA )
1541  i->diffScale = 2 * selfXA / ( dy_ + other->dy_ );
1542  else
1543  i->diffScale = 2 * otherXA / ( dy_ + other->dy_ );
1544  } else if ( doubleEq( i->diffScale, 2 ) ) { // across z plane
1545  double selfXA = dx_ * dy_;
1546  double otherXA = other->dx_ * other->dy_;
1547  if ( selfXA <= otherXA )
1548  i->diffScale = 2 * selfXA / ( dz_ + other->dz_ );
1549  else
1550  i->diffScale = 2 * otherXA / ( dz_ + other->dz_ );
1551  } else {
1552  assert( 0 );
1553  }
1554  }
1555 }
1556 
1558  vector< VoxelJunction >& ret ) const
1559 {
1560 
1561  double myVol = dx_ * dy_ * dz_;
1562  double otherVol = other->dx_ * other->dy_ * other->dz_;
1563  for ( vector< VoxelJunction >::iterator i = ret.begin();
1564  i != ret.end(); ++i )
1565  {
1566  i->firstVol = myVol;
1567  i->secondVol = otherVol;
1568  }
1569 }
static const Cinfo * initCinfo()
Definition: ChemCompt.cpp:25
void setDz(double v)
Definition: CubeMesh.cpp:525
vector< unsigned int > surface_
Definition: CubeMesh.h:345
void assignVoxels(vector< pair< unsigned int, unsigned int > > &intersect, double xmin, double xmax, double ymin, double ymax, double zmin, double zmax) const
Definition: CubeMesh.cpp:1410
vector< unsigned int > getSurface() const
Definition: CubeMesh.cpp:682
void deriveM2sFromS2m()
Definition: CubeMesh.cpp:1033
unsigned int getNx() const
Definition: CubeMesh.cpp:542
static const Cinfo * initCinfo()
Definition: CubeMesh.cpp:31
vector< unsigned int > m2s_
of entries in z in surround volume
Definition: CubeMesh.h:330
unsigned int getNz() const
Definition: CubeMesh.cpp:565
double getDz() const
Definition: CubeMesh.cpp:531
void innerResetStencil()
virtual func implemented here.
Definition: MeshCompt.cpp:49
static const Cinfo * cubeMeshCinfo
Definition: CubeMesh.cpp:256
unsigned int spaceToIndex(double x, double y, double z) const
Converts the 3-D coords to an index. EMPTY if out of range.
Definition: CubeMesh.cpp:1171
unsigned int nz_
of entries in y in surround volume
Definition: CubeMesh.h:313
void deriveS2mFromM2s()
Definition: CubeMesh.cpp:1046
Definition: Dinfo.h:60
unsigned int neighbor(unsigned int spaceIndex, int dx, int dy, int dz) const
Definition: CubeMesh.cpp:822
void addRow(unsigned int index, const vector< double > &entry, const vector< unsigned int > &colIndex)
Definition: MeshCompt.cpp:98
double getX0() const
Definition: CubeMesh.cpp:441
int compareMeshSpacing(const CubeMesh *other) const
Return 0 if spacing same, -1 if self smaller, +1 if self bigger.
Definition: CubeMesh.cpp:1222
void fillThreeDimSurface()
Definition: CubeMesh.cpp:340
double extendedMeshEntryVolume(unsigned int fid) const
Virtual function to return volume of mesh Entry, including.
Definition: MeshCompt.cpp:36
void setX1(double v)
Definition: CubeMesh.cpp:468
void setCoords(const Eref &e, vector< double > v)
Definition: CubeMesh.cpp:629
vector< double > getCoords(const Eref &e) const
Definition: CubeMesh.cpp:636
const vector< double > & getVoxelLength() const
Definition: CubeMesh.cpp:957
double getX1() const
Definition: CubeMesh.cpp:474
double getDx() const
Definition: CubeMesh.cpp:507
void setIntersectVoxel(vector< PII > &intersect, unsigned int ix, unsigned int iy, unsigned int iz, unsigned int nx, unsigned int ny, unsigned int nz, unsigned int meshIndex)
Definition: CubeMesh.cpp:1304
double nearest(double x, double y, double z, unsigned int &index) const
Definition: CubeMesh.cpp:1185
void setY0(double v)
Definition: CubeMesh.cpp:446
void setZ0(double v)
Definition: CubeMesh.cpp:457
const int numEntries
Definition: proc.cpp:60
void matchCubeMeshEntries(const CubeMesh *other, vector< VoxelJunction > &ret) const
Definition: CubeMesh.cpp:1453
double getY1() const
Definition: CubeMesh.cpp:485
void setZ1(double v)
Definition: CubeMesh.cpp:490
vector< double > getDiffusionScaling(unsigned int fid) const
Virtual function to return scale factor for diffusion. 1 here.
Definition: CubeMesh.cpp:881
unsigned int getNy() const
Definition: CubeMesh.cpp:554
static const unsigned int ABUTY
Definition: CubeMesh.h:288
void innerSetCoords(const vector< double > &v)
Definition: CubeMesh.cpp:602
pair< unsigned int, unsigned int > PII
Definition: CubeMesh.cpp:29
void updateCoords()
Definition: CubeMesh.cpp:384
double getZ0() const
Definition: CubeMesh.cpp:463
double x0_
Flag: should all voxels diffuse to any tgt?
Definition: CubeMesh.h:299
const vector< unsigned int > & surface() const
Utility and test function to read surface.
Definition: CubeMesh.cpp:1111
bool isToroid_
Definition: CubeMesh.h:295
static const unsigned int MULTI
Definition: CubeMesh.h:290
void setSpaceToMesh(vector< unsigned int > v)
Definition: CubeMesh.cpp:666
void setIsToroid(bool v)
Definition: CubeMesh.cpp:571
void matchCylMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: CubeMesh.cpp:1516
bool isInsideSpheroid(double x, double y, double z) const
Definition: CubeMesh.cpp:992
static SrcFinfo1< vector< double > > * voxelVolOut()
Definition: ChemCompt.cpp:17
void innerHandleRequestMeshStats(const Eref &e, const SrcFinfo2< unsigned int, vector< double > > *meshStatsFinfo)
More inherited virtual funcs: request comes in for mesh stats.
Definition: CubeMesh.cpp:734
bool doubleApprox(double x, double y)
Definition: doubleEq.cpp:24
void setNx(unsigned int v)
Definition: CubeMesh.cpp:536
const vector< double > & vGetVoxelVolume() const
Virtual func so that derived classes can pass voxel volume back.
Definition: CubeMesh.cpp:917
bool isInsideCuboid(double x, double y, double z) const
Definition: CubeMesh.cpp:986
bool doubleEq(double x, double y)
Definition: doubleEq.cpp:16
double dx_
coords
Definition: CubeMesh.h:307
void matchMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: CubeMesh.cpp:1118
unsigned int innerGetDimensions() const
Definition: CubeMesh.cpp:687
static double distance(double x, double y, double z)
Definition: ChemCompt.cpp:422
vector< unsigned int > getMeshToSpace() const
Definition: CubeMesh.cpp:661
double getY0() const
Definition: CubeMesh.cpp:452
void setAlwaysDiffuse(bool v)
Definition: CubeMesh.cpp:591
void setMeshToSpace(vector< unsigned int > v)
Definition: CubeMesh.cpp:655
vector< unsigned int > getSpaceToMesh() const
Definition: CubeMesh.cpp:672
double y1_
coords
Definition: CubeMesh.h:304
bool getIsToroid() const
Definition: CubeMesh.cpp:576
unsigned int getMeshType(unsigned int fid) const
Virtual function to return MeshType of specified entry.
Definition: CubeMesh.cpp:772
void setNz(unsigned int v)
Definition: CubeMesh.cpp:559
const vector< double > & vGetVoxelMidpoint() const
Virtual func so that derived classes can return voxel midpoint.
Definition: CubeMesh.cpp:925
static const unsigned int SURFACE
Definition: CubeMesh.h:286
void buildStencil()
Definition: CubeMesh.cpp:1060
void defineIntersection(const CubeMesh *other, double &xmin, double &xmax, double &ymin, double &ymax, double &zmin, double &zmax) const
Defines a cuboid volume of intersection between self and other.
Definition: CubeMesh.cpp:1244
vector< double > getDiffusionArea(unsigned int fid) const
Virtual function to return diffusion X-section area.
Definition: CubeMesh.cpp:846
Definition: Eref.h:26
void fillTwoDimSurface()
Fills surface_ vector with spatial meshIndices for a rectangle.
Definition: CubeMesh.cpp:303
bool alwaysDiffuse_
Flag: Should dx change or nx, with vol?
Definition: CubeMesh.h:297
double z1_
coords
Definition: CubeMesh.h:305
void setY1(double v)
Definition: CubeMesh.cpp:479
vector< unsigned int > s2m_
Definition: CubeMesh.h:339
double getZ1() const
Definition: CubeMesh.cpp:496
void fillSpaceToMeshLookup()
Definition: CubeMesh.cpp:1005
void setJunctionVol(const CubeMesh *other, vector< VoxelJunction > &ret) const
Assigns volume info for the voxel junctions.
Definition: CubeMesh.cpp:1557
double vGetEntireVolume() const
Virtual func to get volume of entire compartment.
Definition: CubeMesh.cpp:761
void setDiffScale(const CubeMesh *other, vector< VoxelJunction > &ret) const
Assigns diffusion scaling info for the voxel junctions.
Definition: CubeMesh.cpp:1523
void innerHandleNodeInfo(const Eref &e, unsigned int numNodes, unsigned int numThreads)
Definition: CubeMesh.cpp:743
static unsigned int numNodes
unsigned int nx_
Cuboid edge.
Definition: CubeMesh.h:311
void indexToSpace(unsigned int index, double &x, double &y, double &z) const
Converts the integer meshIndex to spatial coords.
Definition: CubeMesh.cpp:1154
double dz_
Cuboid edge.
Definition: CubeMesh.h:309
void innerSetNumEntries(unsigned int n)
Inherited virtual func.
Definition: CubeMesh.cpp:899
void checkAbut(const vector< PII > &intersect, unsigned int ix, unsigned int iy, unsigned int iz, unsigned int nx, unsigned int ny, unsigned int nz, unsigned int meshIndex, vector< VoxelJunction > &ret)
Definition: CubeMesh.cpp:1348
bool preserveNumEntries_
Flag: Should the ends loop around mathemagically?
Definition: CubeMesh.h:296
void setDy(double v)
Definition: CubeMesh.cpp:513
unsigned int ny_
of entries in x in surround volume
Definition: CubeMesh.h:312
void innerBuildDefaultMesh(const Eref &e, double volume, unsigned int numEntries)
Virtual func to make a mesh with specified Volume and numEntries.
Definition: CubeMesh.cpp:707
static const unsigned int EMPTY
Definition: CubeMesh.h:285
double x1_
coords
Definition: CubeMesh.h:303
double extendedMeshEntryVolume(unsigned int fid) const
Virtual function to return volume of mesh Entry, including.
Definition: CubeMesh.cpp:791
Definition: Id.h:17
vector< double > getCoordinates(unsigned int fid) const
Virtual function to return coords of mesh Entry.
Definition: CubeMesh.cpp:801
void swapIfBackward(double &x0, double &x1)
Definition: CubeMesh.cpp:294
double z0_
coords
Definition: CubeMesh.h:301
static const unsigned int ABUTZ
Definition: CubeMesh.h:289
virtual void matchMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const =0
void matchAllEntries(const CubeMesh *other, vector< VoxelJunction > &ret) const
Definition: CubeMesh.cpp:1503
void setNy(unsigned int v)
Definition: CubeMesh.cpp:548
vector< unsigned int > getParentVoxel() const
Inherited virtual, do nothing for now.
Definition: CubeMesh.cpp:905
void setStencilSize(unsigned int numRows, unsigned int numCols)
Definition: MeshCompt.cpp:106
bool vSetVolumeNotRates(double volume)
Virtual func, assigns volume, usually to single voxel.
Definition: CubeMesh.cpp:969
void setPreserveNumEntries(bool v)
Definition: CubeMesh.cpp:581
const vector< double > & getVoxelArea() const
Definition: CubeMesh.cpp:942
bool getAlwaysDiffuse() const
Definition: CubeMesh.cpp:596
void setAbut(PII &voxel, unsigned int meshIndex, unsigned int axis)
Definition: CubeMesh.cpp:1294
void flipRet(vector< VoxelJunction > &ret) const
Utility function for swapping first and second in VoxelJunctions.
Definition: ChemCompt.cpp:406
static const unsigned int ABUTX
Definition: CubeMesh.h:287
unsigned int getMeshDimensions(unsigned int fid) const
Virtual function to return dimensions of specified entry.
Definition: CubeMesh.cpp:778
double dy_
Cuboid edge.
Definition: CubeMesh.h:308
void matchMeshEntries(const ChemCompt *other, vector< VoxelJunction > &ret) const
Definition: EndoMesh.cpp:420
unsigned int numDims() const
Utility function for returning # of dimensions in mesh.
Definition: CubeMesh.cpp:1148
void setSurface(vector< unsigned int > v)
Definition: CubeMesh.cpp:677
void buildMesh(Id geom, double x, double y, double z)
Definition: CubeMesh.cpp:697
double y0_
coords
Definition: CubeMesh.h:300
double getDy() const
Definition: CubeMesh.cpp:519
Definition: Cinfo.h:18
void setX0(double v)
Definition: CubeMesh.cpp:435
void setDx(double v)
Definition: CubeMesh.cpp:501
Definition: MeshCompt.h:89
bool getPreserveNumEntries() const
Definition: CubeMesh.cpp:586
Definition: OpFunc.h:70
unsigned int innerGetNumEntries() const
Definition: CubeMesh.cpp:891
double getMeshEntryVolume(unsigned int fid) const
Virtual function to return volume of mesh Entry.
Definition: CubeMesh.cpp:784
Definition: Finfo.h:12