Multigrid extension for NeuroFEM 
  last change: 04.03.2008  

New Solver - Data transfer methods

In the process of the data transfer between NeuroFEM and ParExPDE some methods to transfer the data are required. Those methods can be split into two different groups: Methods to acquire informations from NeuroFEM and methods to transfer geometric informations from NeuroFEM to ParExPDE. The five methods of both groups will be explained blow.


Data aquiring methods

The first method of this type is a method to get the geometric position of a node from its number inside the NeuroFEM data structure. Those informations are stored inside of NeuroFEM in a single array where first are stored the x positions, afterwards the y positions and finally the z positions of all nodes. A pointer to this array can be acquired by the VolumeGrid object which was passed to the solver as a creation argument.
Code from file "neurofem/fmg/fmgsolver.cpp"
void FMGSolver::GetNodePosition(int NodeNumber, double* XPos, double* YPos, double* ZPos) {
  double* GridNodePositions = VolumeGrid.getGridNodePosition();
  *XPos = GridNodePositions[NodeNumber-1 + 0*numUnknowns];
  *YPos = GridNodePositions[NodeNumber-1 + 1*numUnknowns];
  *ZPos = GridNodePositions[NodeNumber-1 + 2*numUnknowns];
}

The second important data acquiring method returns a list of nodes belonging to a specific cell (which is internally in NeuroFEM also identified by a number). NeuroFEM stores those informations in a single array where all nodes of a cell are stored together before the nodes of the next cell. This array can be accessed by the VolumeGrid object too.
Code from file "neurofem/fmg/fmgsolver.cpp"
int* FMGSolver::GetCellNodes(int CellNumber) {
  int* localValue = VolumeGrid.getGridElementNodes();
  return localValue + (CellNumber-1)*ElemPerCell;
}


Transformation methods

As an initialization of the transformations methods, it has to be check which dimensions the computational domain has. For this reason the following method checks the size of a single cell and counts how many cells are used in each direction of the computational domain.
Code from file "neurofem/fmg/fmgsolver.cpp"
void FMGSolver::GetBoundingBox() {
  // Check grid width
  int* testcell = GetCellNodes(1);
  double x,z,y;
  maxX = 0.0; maxY = 0.0; maxZ = 0.0; minX = 1e64; minY = 1e64; minZ = 1e64;
  for (int i = 0; i < ElemPerCell; i++) {
    GetNodePosition(testcell[i],&x,&y,&z);
    if (x > maxX) maxX = x;
    if (x < minX) minX = x;
    if (y > maxY) maxY = y;
    if (y < minY) minY = y;
    if (z > maxZ) maxZ = z;
    if (z < minZ) minZ = z;
  }
  deltaX = maxX - minX;
  deltaY = maxY - minY;
  deltaZ = maxZ - minZ;
  // Check the bounding box
  maxX = 0.0; maxY = 0.0; maxZ = 0.0; minX = 1e6; minY = 1e6; minZ = 1e6;
  for (int i = 1; i <= numUnknowns; i++) {
    GetNodePosition(i,&x,&y,&z);
    if (x > maxX) maxX = x;
    if (x < minX) minX = x;
    if (y > maxY) maxY = y;
    if (y < minY) minY = y;
    if (z > maxZ) maxZ = z;
    if (z < minZ) minZ = z;
  }
  // Calculate the required number of cells
  NumCellsX = (int)((maxX - minX) / deltaX + 2.0);
  NumCellsY = (int)((maxY - minY) / deltaY + 2.0);
  NumCellsZ = (int)((maxZ - minZ) / deltaZ + 2.0);
}

One of the two required mapping methods maps a node number of NeuroFEM to three indices required by ParExPDE to identify a cell. To be able to do that, some informations about the size of the computational domain is needed (those are the informations acquired by the method described before).
Code from file "neurofem/fmg/fmgsolver.cpp"
void FMGSolver::MapNodeToIndices(int NodeNumber, int* i, int* j, int* k) {
  double xpos, ypos, zpos;
  GetNodePosition(NodeNumber, &xpos, &ypos, &zpos);
  *i = (int)((xpos - minX) / deltaX) + 1;
  *j = (int)((ypos - minY) / deltaY) + 1;
  *k = (int)((zpos - minZ) / deltaZ) + 1;
}

The second mapping methods maps a cell number of NeuroFEM to three indices required by ParExPDE to identify a cell. For this method can be used, that the first node of a cell is alway to lower, left, front node. Thus the index mapping of the cell is identical to the index mapping of the first node.
Code from file "neurofem/fmg/fmgsolver.cpp"
void FMGSolver::MapCellToIndices(int CellNumber, int* i, int* j, int* k) {
  int* nodes = GetCellNodes(CellNumber);
  MapNodeToIndices(nodes[0],i,j,k);
}