void
MultiAppDTKInterpolationTransfer::execute()
{
  // Every processor has to be involved with every transfer because the "master" domain is on all
  // processors
  // However, each processor might or might not have the particular multiapp on it.  When that
  // happens
  // we need to pass NULL in for the variable and the MPI_Comm for that piece of the transfer
  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
  {
    switch (_direction)
    {
      case TO_MULTIAPP:
      {
        System * from_sys = find_sys(_multi_app->problemBase().es(), _from_var_name);
        System * to_sys = NULL;

        if (_multi_app->hasLocalApp(i))
          to_sys = find_sys(_multi_app->appProblemBase(i).es(), _to_var_name);

        _helper.transferWithOffset(
            0,
            i,
            &from_sys->variable(from_sys->variable_number(_from_var_name)),
            to_sys ? &to_sys->variable(to_sys->variable_number(_to_var_name)) : NULL,
            _master_position,
            _multi_app->position(i),
            const_cast<libMesh::Parallel::communicator *>(&_communicator.get()),
            to_sys ? &_multi_app->comm() : NULL);
        break;
      }

      case FROM_MULTIAPP:
      {
        System * from_sys = NULL;
        System * to_sys = find_sys(_multi_app->problemBase().es(), _to_var_name);

        if (_multi_app->hasLocalApp(i))
          from_sys = find_sys(_multi_app->appProblemBase(i).es(), _from_var_name);

        _helper.transferWithOffset(
            i,
            0,
            from_sys ? &from_sys->variable(from_sys->variable_number(_from_var_name)) : NULL,
            &to_sys->variable(to_sys->variable_number(_to_var_name)),
            _multi_app->position(i),
            _master_position,
            from_sys ? &_multi_app->comm() : NULL,
            const_cast<libMesh::Parallel::communicator *>(&_communicator.get()));
        break;
      }

        _multi_app->problemBase().es().update();

        if (_multi_app->hasLocalApp(i))
          _multi_app->appProblemBase(i).es().update();
    }
  }
}
Ejemplo n.º 2
0
void
DTKAdapter::update_variable_values(std::string var_name)
{
  System * sys = find_sys(var_name);
  unsigned int var_num = sys->variable_number(var_name);

  Teuchos::RCP<FieldContainerType> values = values_to_fill[var_name]->field();

  unsigned int i=0;
  // Loop over the values (one for each node) and assign the value of this variable at each node
  for(FieldContainerType::iterator it=values->begin(); it != values->end(); ++it)
  {
    unsigned int node_num = vertices[i];
    const Node & node = mesh.node(node_num);

    if(node.processor_id() == sys->processor_id())
    {
      // The 0 is for the component... this only works for LAGRANGE!
      dof_id_type dof = node.dof_number(sys->number(), var_num, 0);
      sys->solution->set(dof, *it);
    }

    i++;
  }

  sys->solution->close();
}
Ejemplo n.º 3
0
void
MultiAppTransfer::variableIntegrityCheck(const AuxVariableName & var_name) const
{
  for (unsigned int i = 0; i < _multi_app->numGlobalApps(); i++)
    if (_multi_app->hasLocalApp(i) && !find_sys(_multi_app->appProblem(i)->es(), var_name))
      mooseError("Cannot find variable " << var_name << " for " << name() << " Transfer");
}
Ejemplo n.º 4
0
void
DTKInterpolationAdapter::update_variable_values(std::string var_name, Teuchos::ArrayView<GlobalOrdinal> missed_points)
{
  MPI_Comm old_comm = Moose::swapLibMeshComm(*comm->getRawMpiComm());

  System * sys = find_sys(var_name);
  unsigned int var_num = sys->variable_number(var_name);

  bool is_nodal = sys->variable_type(var_num).family == LAGRANGE;

  Teuchos::RCP<FieldContainerType> values = values_to_fill[var_name]->field();

  // Create a vector containing true or false for each point saying whether it was missed or not
  // We're only going to update values for points that were not missed
  std::vector<bool> missed(values->size(), false);

  for (Teuchos::ArrayView<const GlobalOrdinal>::const_iterator i=missed_points.begin();
      i != missed_points.end();
      ++i)
    missed[*i] = true;

  unsigned int i=0;
  // Loop over the values (one for each node) and assign the value of this variable at each node
  for (FieldContainerType::iterator it=values->begin(); it != values->end(); ++it)
  {
    // If this point "missed" then skip it
    if (missed[i])
    {
      i++;
      continue;
    }

    const DofObject * dof_object = NULL;

    if (is_nodal)
      dof_object = mesh.node_ptr(vertices[i]);
    else
      dof_object = mesh.elem(elements[i]);

    if (dof_object->processor_id() == mesh.processor_id())
    {
      // The 0 is for the component... this only works for LAGRANGE!
      dof_id_type dof = dof_object->dof_number(sys->number(), var_num, 0);
      sys->solution->set(dof, *it);
    }

    i++;
  }

  sys->solution->close();

  // Swap back
  Moose::swapLibMeshComm(old_comm);
}
Ejemplo n.º 5
0
DTKInterpolationAdapter::RCP_Evaluator
DTKInterpolationAdapter::get_variable_evaluator(std::string var_name)
{
  if (evaluators.find(var_name) == evaluators.end()) // We haven't created an evaluator for the variable yet
  {
    System * sys = find_sys(var_name);

    // Create the FieldEvaluator
    evaluators[var_name] = Teuchos::rcp(new DTKInterpolationEvaluator(*sys, var_name, _offset));
  }

  return evaluators[var_name];
}
Ejemplo n.º 6
0
Teuchos::RCP<DataTransferKit::FieldManager<DTKInterpolationAdapter::FieldContainerType> >
DTKInterpolationAdapter::get_values_to_fill(std::string var_name)
{
  if (values_to_fill.find(var_name) == values_to_fill.end())
  {
    System * sys = find_sys(var_name);
    unsigned int var_num = sys->variable_number(var_name);
    bool is_nodal = sys->variable_type(var_num).family == LAGRANGE;

    Teuchos::ArrayRCP<double> data_space;

    if (is_nodal)
      data_space = Teuchos::ArrayRCP<double>(vertices.size());
    else
      data_space = Teuchos::ArrayRCP<double>(elements.size());

    Teuchos::RCP<FieldContainerType> field_container = Teuchos::rcp(new FieldContainerType(data_space, 1));
    values_to_fill[var_name] = Teuchos::rcp(new DataTransferKit::FieldManager<FieldContainerType>(field_container, comm));
  }

  return values_to_fill[var_name];
}
Ejemplo n.º 7
0
static
int
do_loads(int filec, char *filev[], struct membuf *mem,
         int basic_txt_start, int sys_token,
         int *basic_var_startp, int *runp, int trim_sys)
{
    int run = -1;
    int min_start = 65537;
    int max_end = -1;
    int basic_code = 0;
    int i;
    unsigned char *p;
    struct load_info info[1];


    membuf_clear(mem);
    membuf_append(mem, NULL, 65536);
    p = membuf_get(mem);

    for (i = 0; i < filec; ++i)
    {
        info->basic_txt_start = basic_txt_start;
        load_located(filev[i], p, info);
        run = info->run;
        if(run != -1 && runp != NULL)
        {
            LOG(LOG_DEBUG, ("Propagating found run address $%04X.\n",
                            info->run));
            *runp = info->run;
        }

        /* do we expect any basic file? */
        if(basic_txt_start >= 0)
        {
            if(info->basic_var_start >= 0)
            {
                basic_code = 1;
                if(basic_var_startp != NULL)
                {
                    *basic_var_startp = info->basic_var_start;
                }
                if(runp != NULL && run == -1)
                {
                    /* only if we didn't get run address from load_located
                     * (run is not -1 if we did) */
                    int stub_len;
                    run = find_sys(p + basic_txt_start, sys_token, &stub_len);
                    *runp = run;
                    if (trim_sys &&
                        basic_txt_start == info->start &&
                        min_start >= info->start)
                    {
                        if (run >= info->start &&
                            run < info->start + stub_len)
                        {
                            /* the run address points into the sys stub,
                               trim up to it but no further */
                            info->start = run;
                        }
                        else
                        {
                            /* trim the sys stub*/
                            info->start += stub_len;
                        }
                    }
                }
            }
        }

        if (info->start < min_start)
        {
            min_start = info->start;
        }
        if (info->end > max_end)
        {
            max_end = info->end;
        }
    }

    if(basic_txt_start >= 0 && !basic_code && run == -1)
    {
        /* no program loaded to the basic start */
        LOG(LOG_ERROR, ("\nError: nothing loaded at the start of basic "
                        "text address ($%04X).\n",
                        basic_txt_start));
        exit(1);
    }

    /* if we have a basic code loaded and we are doing a proper basic start
     * (the caller don't expect a sys address so runp is NULL */
    if(basic_code && runp == NULL)
    {
        int valuepos = basic_txt_start - 1;
        /* the byte immediatley preceeding the basic start must be 0
         * for basic to function properly. */
        if(min_start > valuepos)
        {
            /* It not covered by the files to crunch. Since the
             * default fill value is 0 we don't need to set it but we
             * need to include that location in the crunch as well. */
            min_start = valuepos;
        }
        else
        {
            int value = p[valuepos];
            /* it has been covered by at least one file. Let's check
             * if it is zero. */
            if(value != 0)
            {
                /* Hm, its not, danger Will Robinson! */
                LOG(LOG_WARNING,
                    ("Warning, basic will probably not work since the value of"
                     " the location \npreceeding the basic start ($%04X)"
                     " is not 0 but %d.\n", valuepos, value));
            }
        }
    }

    /* move memory to beginning of buffer */
    membuf_truncate(mem, max_end);
    membuf_trim(mem, min_start);

    return min_start;
}
void
MultiAppPostprocessorInterpolationTransfer::execute()
{
  switch (_direction)
  {
    case TO_MULTIAPP:
    {
      mooseError("Can't interpolate to a MultiApp!!");
      break;
    }
    case FROM_MULTIAPP:
    {
      InverseDistanceInterpolation<LIBMESH_DIM> * idi;

      switch (_interp_type)
      {
        case 0:
          idi = new InverseDistanceInterpolation<LIBMESH_DIM>(_communicator, _num_points, _power);
          break;
        case 1:
          idi = new RadialBasisInterpolation<LIBMESH_DIM>(_communicator, _radius);
          break;
        default:
          mooseError("Unknown interpolation type!");
      }

      std::vector<Point>  &src_pts  (idi->get_source_points());
      std::vector<Number> &src_vals (idi->get_source_vals());

      std::vector<std::string> field_vars;
      field_vars.push_back(_to_var_name);
      idi->set_field_variables(field_vars);

      {
        for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
        {
          if (_multi_app->hasLocalApp(i) && _multi_app->isRootProcessor())
          {
            src_pts.push_back(_multi_app->position(i));
            src_vals.push_back(_multi_app->appPostprocessorValue(i,_postprocessor));
          }
        }
      }

      // We have only set local values - prepare for use by gathering remote gata
      idi->prepare_for_use();


      // Loop over the master nodes and set the value of the variable
      {
        System * to_sys = find_sys(_multi_app->problem()->es(), _to_var_name);

        unsigned int sys_num = to_sys->number();
        unsigned int var_num = to_sys->variable_number(_to_var_name);

        NumericVector<Real> & solution = *to_sys->solution;

        MooseMesh & mesh = _multi_app->problem()->mesh();

        std::vector<std::string> vars;

        vars.push_back(_to_var_name);

        MeshBase::const_node_iterator node_it = mesh.localNodesBegin();
        MeshBase::const_node_iterator node_end = mesh.localNodesEnd();

        for (; node_it != node_end; ++node_it)
        {
          Node * node = *node_it;

          if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
          {
            std::vector<Point> pts;
            std::vector<Number> vals;

            pts.push_back(*node);
            vals.resize(1);

            idi->interpolate_field_data(vars, pts, vals);

            Real value = vals.front();

            // The zero only works for LAGRANGE!
            dof_id_type dof = node->dof_number(sys_num, var_num, 0);

            solution.set(dof, value);
          }
        }

        solution.close();
      }

      _multi_app->problem()->es().update();

      delete idi;

      break;
    }
  }
}
void
MultiAppMeshFunctionTransfer::execute()
{
  Moose::out << "Beginning MeshFunctionTransfer " << name() << std::endl;

  getAppInfo();

  /**
   * For every combination of global "from" problem and local "to" problem, find
   * which "from" bounding boxes overlap with which "to" elements.  Keep track
   * of which processors own bounding boxes that overlap with which elements.
   * Build vectors of node locations/element centroids to send to other
   * processors for mesh function evaluations.
   */

  // Get the bounding boxes for the "from" domains.
  std::vector<MeshTools::BoundingBox> bboxes = getFromBoundingBoxes();

  // Figure out how many "from" domains each processor owns.
  std::vector<unsigned int> froms_per_proc = getFromsPerProc();

  std::vector<std::vector<Point> > outgoing_points(n_processors());
  std::vector<std::map<std::pair<unsigned int, unsigned int>, unsigned int> > point_index_map(n_processors());
  // point_index_map[i_to, element_id] = index
  // outgoing_points[index] is the first quadrature point in element

  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
  {
    System * to_sys = find_sys(*_to_es[i_to], _to_var_name);
    unsigned int sys_num = to_sys->number();
    unsigned int var_num = to_sys->variable_number(_to_var_name);
    MeshBase * to_mesh = & _to_meshes[i_to]->getMesh();
    bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

    if (is_nodal)
    {
      MeshBase::const_node_iterator node_it = to_mesh->local_nodes_begin();
      MeshBase::const_node_iterator node_end = to_mesh->local_nodes_end();

      for (; node_it != node_end; ++node_it)
      {
        Node * node = *node_it;

        // Skip this node if the variable has no dofs at it.
        if (node->n_dofs(sys_num, var_num) < 1)
          continue;

        // Loop over the "froms" on processor i_proc.  If the node is found in
        // any of the "froms", add that node to the vector that will be sent to
        // i_proc.
        unsigned int from0 = 0;
        for (processor_id_type i_proc = 0;
             i_proc < n_processors();
             from0 += froms_per_proc[i_proc], i_proc++)
        {
          bool point_found = false;
          for (unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && ! point_found; i_from++)
          {
            if (bboxes[i_from].contains_point(*node + _to_positions[i_to]))
            {
              std::pair<unsigned int, unsigned int> key(i_to, node->id());
              point_index_map[i_proc][key] = outgoing_points[i_proc].size();
              outgoing_points[i_proc].push_back(*node + _to_positions[i_to]);
              point_found = true;
            }
          }
        }
      }
    }
    else // Elemental
    {
      MeshBase::const_element_iterator elem_it = to_mesh->local_elements_begin();
      MeshBase::const_element_iterator elem_end = to_mesh->local_elements_end();

      for (; elem_it != elem_end; ++elem_it)
      {
        Elem * elem = *elem_it;

        Point centroid = elem->centroid();

        // Skip this element if the variable has no dofs at it.
        if (elem->n_dofs(sys_num, var_num) < 1)
          continue;

        // Loop over the "froms" on processor i_proc.  If the elem is found in
        // any of the "froms", add that elem to the vector that will be sent to
        // i_proc.
        unsigned int from0 = 0;
        for (processor_id_type i_proc = 0;
             i_proc < n_processors();
             from0 += froms_per_proc[i_proc], i_proc++)
        {
          bool point_found = false;
          for (unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && ! point_found; i_from++)
          {
            if (bboxes[i_from].contains_point(centroid + _to_positions[i_to]))
            {
              std::pair<unsigned int, unsigned int> key(i_to, elem->id());
              point_index_map[i_proc][key] = outgoing_points[i_proc].size();
              outgoing_points[i_proc].push_back(centroid + _to_positions[i_to]);
              point_found = true;
            }
          }
        }
      }
    }
  }

  /**
   * Request point evaluations from other processors and handle requests sent to
   * this processor.
   */

  // Get the local bounding boxes.
  std::vector<MeshTools::BoundingBox> local_bboxes(froms_per_proc[processor_id()]);
  {
    // Find the index to the first of this processor's local bounding boxes.
    unsigned int local_start = 0;
    for (processor_id_type i_proc = 0;
         i_proc < n_processors() && i_proc != processor_id();
         i_proc++)
    {
      local_start += froms_per_proc[i_proc];
    }

    // Extract the local bounding boxes.
    for (unsigned int i_from = 0; i_from < froms_per_proc[processor_id()]; i_from++)
    {
      local_bboxes[i_from] = bboxes[local_start + i_from];
    }
  }

  // Setup the local mesh functions.
  std::vector<MooseSharedPointer<MeshFunction> > local_meshfuns;
  for (unsigned int i_from = 0; i_from < _from_problems.size(); i_from++)
  {
    FEProblem & from_problem = *_from_problems[i_from];
    MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
    System & from_sys = from_var.sys().system();
    unsigned int from_var_num = from_sys.variable_number(from_var.name());

    MooseSharedPointer<MeshFunction> from_func;
    //TODO: make MultiAppTransfer give me the right es
    if (_displaced_source_mesh && from_problem.getDisplacedProblem())
      from_func.reset(new MeshFunction(from_problem.getDisplacedProblem()->es(),
           *from_sys.current_local_solution, from_sys.get_dof_map(), from_var_num));
    else
      from_func.reset(new MeshFunction(from_problem.es(),
           *from_sys.current_local_solution, from_sys.get_dof_map(), from_var_num));
    from_func->init(Trees::ELEMENTS);
    from_func->enable_out_of_mesh_mode(OutOfMeshValue);
    local_meshfuns.push_back(from_func);
  }

  // Send points to other processors.
  std::vector<std::vector<Real> > incoming_evals(n_processors());
  std::vector<std::vector<unsigned int> > incoming_app_ids(n_processors());
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;
    _communicator.send(i_proc, outgoing_points[i_proc]);
  }

  // Recieve points from other processors, evaluate mesh frunctions at those
  // points, and send the values back.
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    std::vector<Point> incoming_points;
    if (i_proc == processor_id())
      incoming_points = outgoing_points[i_proc];
    else
      _communicator.receive(i_proc, incoming_points);

    std::vector<Real> outgoing_evals(incoming_points.size(), OutOfMeshValue);
    std::vector<unsigned int> outgoing_ids(incoming_points.size(), -1); // -1 = largest unsigned int
    for (unsigned int i_pt = 0; i_pt < incoming_points.size(); i_pt++)
    {
      Point pt = incoming_points[i_pt];

      // Loop until we've found the lowest-ranked app that actually contains
      // the quadrature point.
      for (unsigned int i_from = 0; i_from < _from_problems.size() && outgoing_evals[i_pt] == OutOfMeshValue; i_from++)
      {
        if (local_bboxes[i_from].contains_point(pt))
        {
          outgoing_evals[i_pt] = (* local_meshfuns[i_from])(pt - _from_positions[i_from]);
          if (_direction == FROM_MULTIAPP)
            outgoing_ids[i_pt] = _local2global_map[i_from];
        }
      }
    }

    if (i_proc == processor_id())
    {
      incoming_evals[i_proc] = outgoing_evals;
      if (_direction == FROM_MULTIAPP)
        incoming_app_ids[i_proc] = outgoing_ids;
    }
    else
    {
      _communicator.send(i_proc, outgoing_evals);
      if (_direction == FROM_MULTIAPP)
        _communicator.send(i_proc, outgoing_ids);
    }
  }

  /**
   * Gather all of the evaluations, pick out the best ones for each point, and
   * apply them to the solution vector.  When we are transferring from
   * multiapps, there may be multiple overlapping apps for a particular point.
   * In that case, we'll try to use the value from the app with the lowest id.
   */

  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;

    _communicator.receive(i_proc, incoming_evals[i_proc]);
    if (_direction == FROM_MULTIAPP)
      _communicator.receive(i_proc, incoming_app_ids[i_proc]);
  }

  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
  {
    System * to_sys = find_sys(*_to_es[i_to], _to_var_name);

    unsigned int sys_num = to_sys->number();
    unsigned int var_num = to_sys->variable_number(_to_var_name);

    NumericVector<Real> * solution;
    switch (_direction)
    {
      case TO_MULTIAPP:
        solution = & getTransferVector(i_to, _to_var_name);
        break;
      case FROM_MULTIAPP:
        solution = to_sys->solution.get();
        break;
    }

    MeshBase * to_mesh = & _to_meshes[i_to]->getMesh();

    bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

    if (is_nodal)
    {
      MeshBase::const_node_iterator node_it = to_mesh->local_nodes_begin();
      MeshBase::const_node_iterator node_end = to_mesh->local_nodes_end();

      for (; node_it != node_end; ++node_it)
      {
        Node * node = *node_it;

        // Skip this node if the variable has no dofs at it.
        if (node->n_dofs(sys_num, var_num) < 1)
          continue;

        unsigned int lowest_app_rank = libMesh::invalid_uint;
        Real best_val = 0.;
        bool point_found = false;
        for (unsigned int i_proc = 0; i_proc < incoming_evals.size(); i_proc++)
        {
          // Skip this proc if the node wasn't in it's bounding boxes.
          std::pair<unsigned int, unsigned int> key(i_to, node->id());
          if (point_index_map[i_proc].find(key) == point_index_map[i_proc].end())
            continue;
          unsigned int i_pt = point_index_map[i_proc][key];

          // Ignore this proc if it's app has a higher rank than the
          // previously found lowest app rank.
          if (_direction == FROM_MULTIAPP)
          {
            if (incoming_app_ids[i_proc][i_pt] >= lowest_app_rank)
              continue;
          }

          // Ignore this proc if the point was actually outside its meshes.
          if (incoming_evals[i_proc][i_pt] == OutOfMeshValue)
            continue;

          best_val = incoming_evals[i_proc][i_pt];
          point_found = true;
        }

        if (_error_on_miss && ! point_found)
          mooseError("Point not found! " << *node + _to_positions[i_to]);

        dof_id_type dof = node->dof_number(sys_num, var_num, 0);
        solution->set(dof, best_val);
      }
    }
    else // Elemental
    {
      MeshBase::const_element_iterator elem_it = to_mesh->local_elements_begin();
      MeshBase::const_element_iterator elem_end = to_mesh->local_elements_end();

      for (; elem_it != elem_end; ++elem_it)
      {
        Elem * elem = *elem_it;

        // Skip this element if the variable has no dofs at it.
        if (elem->n_dofs(sys_num, var_num) < 1)
          continue;

        unsigned int lowest_app_rank = libMesh::invalid_uint;
        Real best_val = 0;
        bool point_found = false;
        for (unsigned int i_proc = 0; i_proc < incoming_evals.size(); i_proc++)
        {
          // Skip this proc if the elem wasn't in it's bounding boxes.
          std::pair<unsigned int, unsigned int> key(i_to, elem->id());
          if (point_index_map[i_proc].find(key) == point_index_map[i_proc].end())
            continue;
          unsigned int i_pt = point_index_map[i_proc][key];

          // Ignore this proc if it's app has a higher rank than the
          // previously found lowest app rank.
          if (_direction == FROM_MULTIAPP)
          {
            if (incoming_app_ids[i_proc][i_pt] >= lowest_app_rank)
              continue;
          }

          // Ignore this proc if the point was actually outside its meshes.
          if (incoming_evals[i_proc][i_pt] == OutOfMeshValue)
            continue;

          best_val = incoming_evals[i_proc][i_pt];
          point_found = true;
        }

        if (_error_on_miss && ! point_found)
          mooseError("Point not found! " << elem->centroid() + _to_positions[i_to]);

        dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
        solution->set(dof, best_val);
      }
    }
    solution->close();
    to_sys->update();
  }

  _console << "Finished MeshFunctionTransfer " << name() << std::endl;
}
void
MultiAppVariableValueSampleTransfer::execute()
{
  _console << "Beginning VariableValueSampleTransfer " << name() << std::endl;

  switch (_direction)
  {
    case TO_MULTIAPP:
    {
      FEProblem & from_problem = _multi_app->problem();
      MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
      SystemBase & from_system_base = from_var.sys();
      SubProblem & from_sub_problem = from_system_base.subproblem();

      MooseMesh & from_mesh = from_problem.mesh();

      std::unique_ptr<PointLocatorBase> pl = from_mesh.getPointLocator();

      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        Real value = -std::numeric_limits<Real>::max();

        { // Get the value of the variable at the point where this multiapp is in the master domain

          Point multi_app_position = _multi_app->position(i);

          std::vector<Point> point_vec(1, multi_app_position);

          // First find the element the hit lands in
          const Elem * elem = (*pl)(multi_app_position);

          if (elem && elem->processor_id() == from_mesh.processor_id())
          {
            from_sub_problem.reinitElemPhys(elem, point_vec, 0);

            mooseAssert(from_var.sln().size() == 1, "No values in u!");
            value = from_var.sln()[0];
          }

          _communicator.max(value);

          if (value == -std::numeric_limits<Real>::max())
            mooseError("Transfer failed to sample point value at point: " << multi_app_position);
        }

        if (_multi_app->hasLocalApp(i))
        {
          MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

          // Loop over the master nodes and set the value of the variable
          System * to_sys = find_sys(_multi_app->appProblem(i).es(), _to_var_name);

          unsigned int sys_num = to_sys->number();
          unsigned int var_num = to_sys->variable_number(_to_var_name);

          NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);

          MooseMesh & mesh = _multi_app->appProblem(i).mesh();

          MeshBase::const_node_iterator node_it = mesh.localNodesBegin();
          MeshBase::const_node_iterator node_end = mesh.localNodesEnd();

          for (; node_it != node_end; ++node_it)
          {
            Node * node = *node_it;

            if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
            {
              // The zero only works for LAGRANGE!
              dof_id_type dof = node->dof_number(sys_num, var_num, 0);

              solution.set(dof, value);
            }
          }
          solution.close();
          _multi_app->appProblem(i).es().update();

          // Swap back
          Moose::swapLibMeshComm(swapped);
        }
      }

      break;
    }
    case FROM_MULTIAPP:
    {
      mooseError("Doesn't make sense to transfer a sampled variable's value from a MultiApp!!");
      break;
    }
  }

  _console << "Finished VariableValueSampleTransfer " << name() << std::endl;
}
Ejemplo n.º 11
0
void
MultiAppUserObjectTransfer::execute()
{
  _console << "Beginning MultiAppUserObjectTransfer " << name() << std::endl;

  switch (_direction)
  {
    case TO_MULTIAPP:
    {
      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (_multi_app->hasLocalApp(i))
        {
          MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

          // Loop over the master nodes and set the value of the variable
          System * to_sys = find_sys(_multi_app->appProblem(i).es(), _to_var_name);

          unsigned int sys_num = to_sys->number();
          unsigned int var_num = to_sys->variable_number(_to_var_name);

          NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);

          MeshBase * mesh = NULL;

          if (_displaced_target_mesh && _multi_app->appProblem(i).getDisplacedProblem())
          {
            mesh = &_multi_app->appProblem(i).getDisplacedProblem()->mesh().getMesh();
          }
          else
            mesh = &_multi_app->appProblem(i).mesh().getMesh();

          bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

          const UserObject & user_object = _multi_app->problem().getUserObjectBase(_user_object_name);

          if (is_nodal)
          {
            MeshBase::const_node_iterator node_it = mesh->local_nodes_begin();
            MeshBase::const_node_iterator node_end = mesh->local_nodes_end();

            for (; node_it != node_end; ++node_it)
            {
              Node * node = *node_it;

              if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
              {
                // The zero only works for LAGRANGE!
                dof_id_type dof = node->dof_number(sys_num, var_num, 0);

                // Swap back
                Moose::swapLibMeshComm(swapped);
                Real from_value = user_object.spatialValue(*node+_multi_app->position(i));
                // Swap again
                swapped = Moose::swapLibMeshComm(_multi_app->comm());

                solution.set(dof, from_value);
              }
            }
          }
          else // Elemental
          {
            MeshBase::const_element_iterator elem_it = mesh->local_elements_begin();
            MeshBase::const_element_iterator elem_end = mesh->local_elements_end();

            for (; elem_it != elem_end; ++elem_it)
            {
              Elem * elem = *elem_it;

              Point centroid = elem->centroid();

              if (elem->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this elem
              {
                // The zero only works for LAGRANGE!
                dof_id_type dof = elem->dof_number(sys_num, var_num, 0);

                // Swap back
                Moose::swapLibMeshComm(swapped);
                Real from_value = user_object.spatialValue(centroid+_multi_app->position(i));
                // Swap again
                swapped = Moose::swapLibMeshComm(_multi_app->comm());

                solution.set(dof, from_value);
              }
            }
          }

          solution.close();
          to_sys->update();

          // Swap back
          Moose::swapLibMeshComm(swapped);
        }
      }

      break;
    }
    case FROM_MULTIAPP:
    {
      FEProblem & to_problem = _multi_app->problem();
      MooseVariable & to_var = to_problem.getVariable(0, _to_var_name);
      SystemBase & to_system_base = to_var.sys();

      System & to_sys = to_system_base.system();

      unsigned int to_sys_num = to_sys.number();

      // Only works with a serialized mesh to transfer to!
      mooseAssert(to_sys.get_mesh().is_serial(), "MultiAppUserObjectTransfer only works with SerialMesh!");

      unsigned int to_var_num = to_sys.variable_number(to_var.name());

      _console << "Transferring to: " << to_var.name() << std::endl;

      // EquationSystems & to_es = to_sys.get_equation_systems();

      //Create a serialized version of the solution vector
      NumericVector<Number> * to_solution = to_sys.solution.get();

      MeshBase * to_mesh = NULL;

      if (_displaced_target_mesh && to_problem.getDisplacedProblem())
        to_mesh = &to_problem.getDisplacedProblem()->mesh().getMesh();
      else
        to_mesh = &to_problem.mesh().getMesh();

      bool is_nodal = to_sys.variable_type(to_var_num).family == LAGRANGE;

      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (!_multi_app->hasLocalApp(i))
          continue;

        Point app_position = _multi_app->position(i);
        MeshTools::BoundingBox app_box = _multi_app->getBoundingBox(i);
        const UserObject & user_object = _multi_app->appUserObjectBase(i, _user_object_name);

        if (is_nodal)
        {
          MeshBase::const_node_iterator node_it = to_mesh->nodes_begin();
          MeshBase::const_node_iterator node_end = to_mesh->nodes_end();

          for (; node_it != node_end; ++node_it)
          {
            Node * node = *node_it;

            if (node->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this node
            {
              // See if this node falls in this bounding box
              if (app_box.contains_point(*node))
              {
                dof_id_type dof = node->dof_number(to_sys_num, to_var_num, 0);

                MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());
                Real from_value = user_object.spatialValue(*node-app_position);
                Moose::swapLibMeshComm(swapped);

                to_solution->set(dof, from_value);
              }
            }
          }
        }
        else // Elemental
        {
          MeshBase::const_element_iterator elem_it = to_mesh->elements_begin();
          MeshBase::const_element_iterator elem_end = to_mesh->elements_end();

          for (; elem_it != elem_end; ++elem_it)
          {
            Elem * elem = *elem_it;

            if (elem->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this elem
            {
              Point centroid = elem->centroid();

              // See if this elem falls in this bounding box
              if (app_box.contains_point(centroid))
              {
                dof_id_type dof = elem->dof_number(to_sys_num, to_var_num, 0);

                MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());
                Real from_value = user_object.spatialValue(centroid-app_position);
                Moose::swapLibMeshComm(swapped);

                to_solution->set(dof, from_value);
              }
            }
          }
        }
      }

      to_solution->close();
      to_sys.update();

      break;
    }
  }

  _console << "Finished MultiAppUserObjectTransfer " << name() << std::endl;
}
Ejemplo n.º 12
0
void
MultiAppMeshFunctionTransfer::execute()
{
    Moose::out << "Beginning MeshFunctionTransfer " << _name << std::endl;

    switch(_direction)
    {
    case TO_MULTIAPP:
    {
        FEProblem & from_problem = *_multi_app->problem();
        MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
        SystemBase & from_system_base = from_var.sys();

        System & from_sys = from_system_base.system();

        // Only works with a serialized mesh to transfer from!
        mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppMeshFunctionTransfer only works with SerialMesh!");

        unsigned int from_var_num = from_sys.variable_number(from_var.name());

        EquationSystems & from_es = from_sys.get_equation_systems();

        //Create a serialized version of the solution vector
        NumericVector<Number> * serialized_solution = NumericVector<Number>::build().release();
        serialized_solution->init(from_sys.n_dofs(), false, SERIAL);

        // Need to pull down a full copy of this vector on every processor so we can get values in parallel
        from_sys.solution->localize(*serialized_solution);

        MeshFunction from_func(from_es, *serialized_solution, from_sys.get_dof_map(), from_var_num);
        from_func.init(Trees::ELEMENTS);
        from_func.enable_out_of_mesh_mode(NOTFOUND);

        for(unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
        {
            if (_multi_app->hasLocalApp(i))
            {
                MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

                // Loop over the master nodes and set the value of the variable
                System * to_sys = find_sys(_multi_app->appProblem(i)->es(), _to_var_name);

                if (!to_sys)
                    mooseError("Cannot find variable "<<_to_var_name<<" for "<<_name<<" Transfer");

                unsigned int sys_num = to_sys->number();
                unsigned int var_num = to_sys->variable_number(_to_var_name);
                NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);

                MeshBase & mesh = _multi_app->appProblem(i)->mesh().getMesh();
                bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

                if (is_nodal)
                {
                    MeshBase::const_node_iterator node_it = mesh.local_nodes_begin();
                    MeshBase::const_node_iterator node_end = mesh.local_nodes_end();

                    for(; node_it != node_end; ++node_it)
                    {
                        Node * node = *node_it;

                        if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
                        {
                            // The zero only works for LAGRANGE!
                            dof_id_type dof = node->dof_number(sys_num, var_num, 0);

                            // Swap back
                            Moose::swapLibMeshComm(swapped);
                            Real from_value = from_func(*node+_multi_app->position(i));
                            // Swap again
                            swapped = Moose::swapLibMeshComm(_multi_app->comm());

                            if (from_value != NOTFOUND)
                                solution.set(dof, from_value);
                            else if (_error_on_miss)
                                mooseError("Point not found! " << *node+_multi_app->position(i) << std::endl);
                        }
                    }
                }
                else // Elemental
                {
                    MeshBase::const_element_iterator elem_it = mesh.local_elements_begin();
                    MeshBase::const_element_iterator elem_end = mesh.local_elements_end();

                    for(; elem_it != elem_end; ++elem_it)
                    {
                        Elem * elem = *elem_it;

                        Point centroid = elem->centroid();

                        if (elem->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this elem
                        {
                            // The zero only works for LAGRANGE!
                            dof_id_type dof = elem->dof_number(sys_num, var_num, 0);

                            // Swap back
                            Moose::swapLibMeshComm(swapped);
                            Real from_value = from_func(centroid+_multi_app->position(i));
                            // Swap again
                            swapped = Moose::swapLibMeshComm(_multi_app->comm());

                            if (from_value != NOTFOUND)
                                solution.set(dof, from_value);
                            else if (_error_on_miss)
                                mooseError("Point not found! " << centroid+_multi_app->position(i) << std::endl);
                        }
                    }
                }

                solution.close();
                to_sys->update();

                // Swap back
                Moose::swapLibMeshComm(swapped);
            }
        }

        delete serialized_solution;

        break;
    }
    case FROM_MULTIAPP:
    {
        FEProblem & to_problem = *_multi_app->problem();
        MooseVariable & to_var = to_problem.getVariable(0, _to_var_name);
        SystemBase & to_system_base = to_var.sys();

        System & to_sys = to_system_base.system();

        unsigned int to_sys_num = to_sys.number();

        // Only works with a serialized mesh to transfer to!
        mooseAssert(to_sys.get_mesh().is_serial(), "MultiAppMeshFunctionTransfer only works with SerialMesh!");

        unsigned int to_var_num = to_sys.variable_number(to_var.name());

        EquationSystems & to_es = to_sys.get_equation_systems();

        NumericVector<Number> * to_solution = to_sys.solution.get();

        MeshBase & to_mesh = to_es.get_mesh();

        bool is_nodal = to_sys.variable_type(to_var_num).family == LAGRANGE;

        for(unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
        {
            if (!_multi_app->hasLocalApp(i))
                continue;

            MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());
            FEProblem & from_problem = *_multi_app->appProblem(i);
            MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
            SystemBase & from_system_base = from_var.sys();

            System & from_sys = from_system_base.system();

            // Only works with a serialized mesh to transfer from!
            mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppMeshFunctionTransfer only works with SerialMesh!");

            unsigned int from_var_num = from_sys.variable_number(from_var.name());

            EquationSystems & from_es = from_sys.get_equation_systems();

            //Create a serialized version of the solution vector
            NumericVector<Number> * serialized_from_solution = NumericVector<Number>::build().release();
            serialized_from_solution->init(from_sys.n_dofs(), false, SERIAL);

            // Need to pull down a full copy of this vector on every processor so we can get values in parallel
            from_sys.solution->localize(*serialized_from_solution);

            MeshBase & from_mesh = from_es.get_mesh();
            MeshTools::BoundingBox app_box = MeshTools::processor_bounding_box(from_mesh, libMesh::processor_id());
            Point app_position = _multi_app->position(i);

            MeshFunction from_func(from_es, *serialized_from_solution, from_sys.get_dof_map(), from_var_num);
            from_func.init(Trees::ELEMENTS);
            from_func.enable_out_of_mesh_mode(NOTFOUND);
            Moose::swapLibMeshComm(swapped);

            if (is_nodal)
            {
                MeshBase::const_node_iterator node_it = to_mesh.nodes_begin();
                MeshBase::const_node_iterator node_end = to_mesh.nodes_end();

                for(; node_it != node_end; ++node_it)
                {
                    Node * node = *node_it;

                    if (node->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this node
                    {
                        // See if this node falls in this bounding box
                        if (app_box.contains_point(*node-app_position))
                        {
                            // The zero only works for LAGRANGE!
                            dof_id_type dof = node->dof_number(to_sys_num, to_var_num, 0);

                            MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());
                            Real from_value = from_func(*node-app_position);
                            Moose::swapLibMeshComm(swapped);

                            if (from_value != NOTFOUND)
                                to_solution->set(dof, from_value);
                            else if (_error_on_miss)
                                mooseError("Point not found! " << *node-app_position <<std::endl);
                        }
                    }
                }
            }
            else // Elemental
            {
                MeshBase::const_element_iterator elem_it = to_mesh.elements_begin();
                MeshBase::const_element_iterator elem_end = to_mesh.elements_end();

                for(; elem_it != elem_end; ++elem_it)
                {
                    Elem * elem = *elem_it;

                    if (elem->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this elem
                    {
                        Point centroid = elem->centroid();

                        // See if this elem falls in this bounding box
                        if (app_box.contains_point(centroid-app_position))
                        {
                            // The zero only works for LAGRANGE!
                            dof_id_type dof = elem->dof_number(to_sys_num, to_var_num, 0);

                            MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());
                            Real from_value = from_func(centroid-app_position);
                            Moose::swapLibMeshComm(swapped);

                            if (from_value != NOTFOUND)
                                to_solution->set(dof, from_value);
                            else if (_error_on_miss)
                                mooseError("Point not found! " << centroid-app_position << std::endl);
                        }
                    }
                }
            }
            delete serialized_from_solution;
        }

        to_solution->close();
        to_sys.update();

        break;
    }
    }

    Moose::out << "Finished MeshFunctionTransfer " << _name << std::endl;
}
Ejemplo n.º 13
0
void
MultiAppInterpolationTransfer::execute()
{
  _console << "Beginning InterpolationTransfer " << _name << std::endl;

  switch (_direction)
  {
    case TO_MULTIAPP:
    {
      FEProblem & from_problem = *_multi_app->problem();
      MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);

      MeshBase * from_mesh = NULL;

      if (_displaced_source_mesh && from_problem.getDisplacedProblem())
        from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh();
      else
        from_mesh = &from_problem.mesh().getMesh();

      SystemBase & from_system_base = from_var.sys();
      System & from_sys = from_system_base.system();

      unsigned int from_sys_num = from_sys.number();
      unsigned int from_var_num = from_sys.variable_number(from_var.name());

      bool from_is_nodal = from_sys.variable_type(from_var_num).family == LAGRANGE;

      // EquationSystems & from_es = from_sys.get_equation_systems();

      NumericVector<Number> & from_solution = *from_sys.solution;

      InverseDistanceInterpolation<LIBMESH_DIM> * idi;

      switch (_interp_type)
      {
        case 0:
          idi = new InverseDistanceInterpolation<LIBMESH_DIM>(from_sys.comm(), _num_points, _power);
          break;
        case 1:
          idi = new RadialBasisInterpolation<LIBMESH_DIM>(from_sys.comm(), _radius);
          break;
        default:
          mooseError("Unknown interpolation type!");
      }

      std::vector<Point>  &src_pts  (idi->get_source_points());
      std::vector<Number> &src_vals (idi->get_source_vals());

      std::vector<std::string> field_vars;
      field_vars.push_back(_to_var_name);
      idi->set_field_variables(field_vars);

      std::vector<std::string> vars;
      vars.push_back(_to_var_name);

      if (from_is_nodal)
      {
        MeshBase::const_node_iterator from_nodes_it    = from_mesh->local_nodes_begin();
        MeshBase::const_node_iterator from_nodes_end   = from_mesh->local_nodes_end();

        for (; from_nodes_it != from_nodes_end; ++from_nodes_it)
        {
          Node * from_node = *from_nodes_it;

          // Assuming LAGRANGE!
          dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);

          src_pts.push_back(*from_node);
          src_vals.push_back(from_solution(from_dof));
        }
      }
      else
      {
        MeshBase::const_element_iterator from_elements_it    = from_mesh->local_elements_begin();
        MeshBase::const_element_iterator from_elements_end   = from_mesh->local_elements_end();

        for (; from_elements_it != from_elements_end; ++from_elements_it)
        {
          Elem * from_elem = *from_elements_it;

          // Assuming CONSTANT MONOMIAL
          dof_id_type from_dof = from_elem->dof_number(from_sys_num, from_var_num, 0);

          src_pts.push_back(from_elem->centroid());
          src_vals.push_back(from_solution(from_dof));
        }
      }

      // We have only set local values - prepare for use by gathering remote gata
      idi->prepare_for_use();

      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (_multi_app->hasLocalApp(i))
        {
          MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

          // Loop over the master nodes and set the value of the variable
          System * to_sys = find_sys(_multi_app->appProblem(i)->es(), _to_var_name);

          unsigned int sys_num = to_sys->number();
          unsigned int var_num = to_sys->variable_number(_to_var_name);
          NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);

          MeshBase * mesh = NULL;

          if (_displaced_target_mesh && _multi_app->appProblem(i)->getDisplacedProblem())
            mesh = &_multi_app->appProblem(i)->getDisplacedProblem()->mesh().getMesh();
          else
            mesh = &_multi_app->appProblem(i)->mesh().getMesh();

          bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

          if (is_nodal)
          {
            MeshBase::const_node_iterator node_it = mesh->local_nodes_begin();
            MeshBase::const_node_iterator node_end = mesh->local_nodes_end();

            for (; node_it != node_end; ++node_it)
            {
              Node * node = *node_it;

              Point actual_position = *node+_multi_app->position(i);

              if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
              {
                std::vector<Point> pts;
                std::vector<Number> vals;

                pts.push_back(actual_position);
                vals.resize(1);

                idi->interpolate_field_data(vars, pts, vals);

                Real value = vals.front();

                // The zero only works for LAGRANGE!
                dof_id_type dof = node->dof_number(sys_num, var_num, 0);

                solution.set(dof, value);
              }
            }
          }
          else // Elemental
          {
            MeshBase::const_element_iterator elem_it = mesh->local_elements_begin();
            MeshBase::const_element_iterator elem_end = mesh->local_elements_end();

            for (; elem_it != elem_end; ++elem_it)
            {
              Elem * elem = *elem_it;

              Point centroid = elem->centroid();
              Point actual_position = centroid+_multi_app->position(i);

              if (elem->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this elem
              {
                std::vector<Point> pts;
                std::vector<Number> vals;

                pts.push_back(actual_position);
                vals.resize(1);

                idi->interpolate_field_data(vars, pts, vals);

                Real value = vals.front();

                dof_id_type dof = elem->dof_number(sys_num, var_num, 0);

                solution.set(dof, value);
              }
            }
          }

          solution.close();
          to_sys->update();

          // Swap back
          Moose::swapLibMeshComm(swapped);
        }
      }

      delete idi;

      break;
    }
    case FROM_MULTIAPP:
    {
      FEProblem & to_problem = *_multi_app->problem();
      MooseVariable & to_var = to_problem.getVariable(0, _to_var_name);
      SystemBase & to_system_base = to_var.sys();

      System & to_sys = to_system_base.system();

      NumericVector<Real> & to_solution = *to_sys.solution;

      unsigned int to_sys_num = to_sys.number();

      // Only works with a serialized mesh to transfer to!
      mooseAssert(to_sys.get_mesh().is_serial(), "MultiAppInterpolationTransfer only works with SerialMesh!");

      unsigned int to_var_num = to_sys.variable_number(to_var.name());

      // EquationSystems & to_es = to_sys.get_equation_systems();

      MeshBase * to_mesh = NULL;

      if (_displaced_target_mesh && to_problem.getDisplacedProblem())
        to_mesh = &to_problem.getDisplacedProblem()->mesh().getMesh();
      else
        to_mesh = &to_problem.mesh().getMesh();

      bool is_nodal = to_sys.variable_type(to_var_num).family == LAGRANGE;

      InverseDistanceInterpolation<LIBMESH_DIM> * idi;

      switch (_interp_type)
      {
        case 0:
          idi = new InverseDistanceInterpolation<LIBMESH_DIM>(to_sys.comm(), _num_points, _power);
          break;
        case 1:
          idi = new RadialBasisInterpolation<LIBMESH_DIM>(to_sys.comm(), _radius);
          break;
        default:
          mooseError("Unknown interpolation type!");
      }

      std::vector<Point>  &src_pts  (idi->get_source_points());
      std::vector<Number> &src_vals (idi->get_source_vals());

      std::vector<std::string> field_vars;
      field_vars.push_back(_to_var_name);
      idi->set_field_variables(field_vars);

      std::vector<std::string> vars;
      vars.push_back(_to_var_name);

      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (!_multi_app->hasLocalApp(i))
          continue;

        MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

        FEProblem & from_problem = *_multi_app->appProblem(i);
        MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
        SystemBase & from_system_base = from_var.sys();

        System & from_sys = from_system_base.system();
        unsigned int from_sys_num = from_sys.number();

        unsigned int from_var_num = from_sys.variable_number(from_var.name());

        bool from_is_nodal = from_sys.variable_type(from_var_num).family == LAGRANGE;

        // EquationSystems & from_es = from_sys.get_equation_systems();

        NumericVector<Number> & from_solution = *from_sys.solution;

        MeshBase * from_mesh = NULL;

        if (_displaced_source_mesh && from_problem.getDisplacedProblem())
          from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh();
        else
          from_mesh = &from_problem.mesh().getMesh();

        Point app_position = _multi_app->position(i);

        if (from_is_nodal)
        {
          MeshBase::const_node_iterator from_nodes_it    = from_mesh->local_nodes_begin();
          MeshBase::const_node_iterator from_nodes_end   = from_mesh->local_nodes_end();

          for (; from_nodes_it != from_nodes_end; ++from_nodes_it)
          {
            Node * from_node = *from_nodes_it;

            // Assuming LAGRANGE!
            dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);

            src_pts.push_back(*from_node+app_position);
            src_vals.push_back(from_solution(from_dof));
          }
        }
        else
        {
          MeshBase::const_element_iterator from_elements_it    = from_mesh->local_elements_begin();
          MeshBase::const_element_iterator from_elements_end   = from_mesh->local_elements_end();

          for (; from_elements_it != from_elements_end; ++from_elements_it)
          {
            Elem * from_element = *from_elements_it;

            // Assuming LAGRANGE!
            dof_id_type from_dof = from_element->dof_number(from_sys_num, from_var_num, 0);

            src_pts.push_back(from_element->centroid()+app_position);
            src_vals.push_back(from_solution(from_dof));
          }
        }

        Moose::swapLibMeshComm(swapped);
      }

      // We have only set local values - prepare for use by gathering remote gata
      idi->prepare_for_use();

      // Now do the interpolation to the target system
      if (is_nodal)
      {
        MeshBase::const_node_iterator node_it = to_mesh->local_nodes_begin();
        MeshBase::const_node_iterator node_end = to_mesh->local_nodes_end();

        for (; node_it != node_end; ++node_it)
        {
          Node * node = *node_it;

          if (node->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this node
          {
            std::vector<Point> pts;
            std::vector<Number> vals;

            pts.push_back(*node);
            vals.resize(1);

            idi->interpolate_field_data(vars, pts, vals);

            Real value = vals.front();

            // The zero only works for LAGRANGE!
            dof_id_type dof = node->dof_number(to_sys_num, to_var_num, 0);

            to_solution.set(dof, value);
          }
        }
      }
      else // Elemental
      {
        MeshBase::const_element_iterator elem_it = to_mesh->local_elements_begin();
        MeshBase::const_element_iterator elem_end = to_mesh->local_elements_end();

        for (; elem_it != elem_end; ++elem_it)
        {
          Elem * elem = *elem_it;

          Point centroid = elem->centroid();

          if (elem->n_dofs(to_sys_num, to_var_num) > 0) // If this variable has dofs at this elem
          {
            std::vector<Point> pts;
            std::vector<Number> vals;

            pts.push_back(centroid);
            vals.resize(1);

            idi->interpolate_field_data(vars, pts, vals);

            Real value = vals.front();

            dof_id_type dof = elem->dof_number(to_sys_num, to_var_num, 0);

            to_solution.set(dof, value);
          }
        }
      }

      to_solution.close();
      to_sys.update();

      delete idi;

      break;
    }
  }

  _console << "Finished InterpolationTransfer " << _name << std::endl;
}
Ejemplo n.º 14
0
void
MultiAppNearestNodeTransfer::execute()
{
  _console << "Beginning NearestNodeTransfer " << name() << std::endl;

  getAppInfo();

  // Get the bounding boxes for the "from" domains.
  std::vector<BoundingBox> bboxes;
  if (isParamValid("source_boundary"))
    bboxes = getFromBoundingBoxes(
        _from_meshes[0]->getBoundaryID(getParam<BoundaryName>("source_boundary")));
  else
    bboxes = getFromBoundingBoxes();

  // Figure out how many "from" domains each processor owns.
  std::vector<unsigned int> froms_per_proc = getFromsPerProc();

  ////////////////////
  // For every point in the local "to" domain, figure out which "from" domains
  // might contain it's nearest neighbor, and send that point to the processors
  // that own those "from" domains.
  //
  // How do we know which "from" domains might contain the nearest neighbor, you
  // ask?  Well, consider two "from" domains, A and B.  If every point in A is
  // closer than every point in B, then we know that B cannot possibly contain
  // the nearest neighbor.  Hence, we'll only check A for the nearest neighbor.
  // We'll use the functions bboxMaxDistance and bboxMinDistance to figure out
  // if every point in A is closer than every point in B.
  ////////////////////

  // outgoing_qps = nodes/centroids we'll send to other processors.
  std::vector<std::vector<Point>> outgoing_qps(n_processors());
  // When we get results back, node_index_map will tell us which results go with
  // which points
  std::vector<std::map<std::pair<unsigned int, unsigned int>, unsigned int>> node_index_map(
      n_processors());

  if (!_neighbors_cached)
  {
    for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
    {
      System * to_sys = find_sys(*_to_es[i_to], _to_var_name);
      unsigned int sys_num = to_sys->number();
      unsigned int var_num = to_sys->variable_number(_to_var_name);
      MeshBase * to_mesh = &_to_meshes[i_to]->getMesh();
      bool is_to_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

      if (is_to_nodal)
      {
        std::vector<Node *> target_local_nodes;

        if (isParamValid("target_boundary"))
        {
          BoundaryID target_bnd_id =
              _to_meshes[i_to]->getBoundaryID(getParam<BoundaryName>("target_boundary"));

          ConstBndNodeRange & bnd_nodes = *(_to_meshes[i_to])->getBoundaryNodeRange();
          for (const auto & bnode : bnd_nodes)
            if (bnode->_bnd_id == target_bnd_id && bnode->_node->processor_id() == processor_id())
              target_local_nodes.push_back(bnode->_node);
        }
        else
        {
          target_local_nodes.resize(to_mesh->n_local_nodes());
          unsigned int i = 0;
          for (auto & node : to_mesh->local_node_ptr_range())
            target_local_nodes[i++] = node;
        }

        // For error checking: keep track of all target_local_nodes
        // which are successfully mapped to at least one domain where
        // the nearest neighbor might be found.
        std::set<Node *> local_nodes_found;

        for (const auto & node : target_local_nodes)
        {
          // Skip this node if the variable has no dofs at it.
          if (node->n_dofs(sys_num, var_num) < 1)
            continue;

          // Find which bboxes might have the nearest node to this point.
          Real nearest_max_distance = std::numeric_limits<Real>::max();
          for (const auto & bbox : bboxes)
          {
            Real distance = bboxMaxDistance(*node, bbox);
            if (distance < nearest_max_distance)
              nearest_max_distance = distance;
          }

          unsigned int from0 = 0;
          for (processor_id_type i_proc = 0; i_proc < n_processors();
               from0 += froms_per_proc[i_proc], i_proc++)
          {
            bool qp_found = false;

            for (unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && !qp_found;
                 i_from++)
            {

              Real distance = bboxMinDistance(*node, bboxes[i_from]);

              if (distance <= nearest_max_distance || bboxes[i_from].contains_point(*node))
              {
                std::pair<unsigned int, unsigned int> key(i_to, node->id());
                node_index_map[i_proc][key] = outgoing_qps[i_proc].size();
                outgoing_qps[i_proc].push_back(*node + _to_positions[i_to]);
                qp_found = true;
                local_nodes_found.insert(node);
              }
            }
          }
        }

        // By the time we get to here, we should have found at least
        // one candidate BoundingBox for every node in the
        // target_local_nodes array that has dofs for the current
        // variable in the current System.
        for (const auto & node : target_local_nodes)
          if (node->n_dofs(sys_num, var_num) && !local_nodes_found.count(node))
            mooseError("In ",
                       name(),
                       ": No candidate BoundingBoxes found for node ",
                       node->id(),
                       " at position ",
                       *node);
      }
      else // Elemental
      {
        // For error checking: keep track of all local elements
        // which are successfully mapped to at least one domain where
        // the nearest neighbor might be found.
        std::set<Elem *> local_elems_found;

        for (auto & elem : as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
        {
          Point centroid = elem->centroid();

          // Skip this element if the variable has no dofs at it.
          if (elem->n_dofs(sys_num, var_num) < 1)
            continue;

          // Find which bboxes might have the nearest node to this point.
          Real nearest_max_distance = std::numeric_limits<Real>::max();
          for (const auto & bbox : bboxes)
          {
            Real distance = bboxMaxDistance(centroid, bbox);
            if (distance < nearest_max_distance)
              nearest_max_distance = distance;
          }

          unsigned int from0 = 0;
          for (processor_id_type i_proc = 0; i_proc < n_processors();
               from0 += froms_per_proc[i_proc], i_proc++)
          {
            bool qp_found = false;
            for (unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && !qp_found;
                 i_from++)
            {
              Real distance = bboxMinDistance(centroid, bboxes[i_from]);
              if (distance <= nearest_max_distance || bboxes[i_from].contains_point(centroid))
              {
                std::pair<unsigned int, unsigned int> key(i_to, elem->id());
                node_index_map[i_proc][key] = outgoing_qps[i_proc].size();
                outgoing_qps[i_proc].push_back(centroid + _to_positions[i_to]);
                qp_found = true;
                local_elems_found.insert(elem);
              }
            }
          }
        }

        // Verify that we found at least one candidate bounding
        // box for each local element with dofs for the current
        // variable in the current System.
        for (auto & elem : as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
          if (elem->n_dofs(sys_num, var_num) && !local_elems_found.count(elem))
            mooseError("In ",
                       name(),
                       ": No candidate BoundingBoxes found for Elem ",
                       elem->id(),
                       ", centroid = ",
                       elem->centroid());
      }
    }
  }

  ////////////////////
  // Send local node/centroid positions off to the other processors and take
  // care of points sent to this processor.  We'll need to check the points
  // against all of the "from" domains that this processor owns.  For each
  // point, we'll find the nearest node, then we'll send the value at that node
  // and the distance between the node and the point back to the processor that
  // requested that point.
  ////////////////////

  std::vector<std::vector<Real>> incoming_evals(n_processors());
  std::vector<Parallel::Request> send_qps(n_processors());
  std::vector<Parallel::Request> send_evals(n_processors());

  // Create these here so that they live the entire life of this function
  // and are NOT reused per processor.
  std::vector<std::vector<Real>> processor_outgoing_evals(n_processors());

  if (!_neighbors_cached)
  {
    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
    {
      if (i_proc == processor_id())
        continue;
      _communicator.send(i_proc, outgoing_qps[i_proc], send_qps[i_proc]);
    }

    // Build an array of pointers to all of this processor's local entities (nodes or
    // elements).  We need to do this to avoid the expense of using LibMesh iterators.
    // This step also takes care of limiting the search to boundary nodes, if
    // applicable.
    std::vector<std::vector<std::pair<Point, DofObject *>>> local_entities(
        froms_per_proc[processor_id()]);

    // Local array of all from Variable references
    std::vector<std::reference_wrapper<MooseVariableFEBase>> _from_vars;

    for (unsigned int i = 0; i < froms_per_proc[processor_id()]; i++)
    {
      MooseVariableFEBase & from_var = _from_problems[i]->getVariable(
          0, _from_var_name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_STANDARD);
      bool is_to_nodal = from_var.feType().family == LAGRANGE;

      _from_vars.emplace_back(from_var);
      getLocalEntities(_from_meshes[i], local_entities[i], is_to_nodal);
    }

    if (_fixed_meshes)
    {
      _cached_froms.resize(n_processors());
      _cached_dof_ids.resize(n_processors());
    }

    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
    {
      // We either use our own outgoing_qps or receive them from
      // another processor.
      std::vector<Point> incoming_qps;
      if (i_proc == processor_id())
        incoming_qps = outgoing_qps[i_proc];
      else
        _communicator.receive(i_proc, incoming_qps);

      if (_fixed_meshes)
      {
        _cached_froms[i_proc].resize(incoming_qps.size());
        _cached_dof_ids[i_proc].resize(incoming_qps.size());
      }

      std::vector<Real> & outgoing_evals = processor_outgoing_evals[i_proc];
      // Resize this vector to two times the size of the incoming_qps
      // vector because we are going to store both the value from the nearest
      // local node *and* the distance between the incoming_qp and that node
      // for later comparison purposes.
      outgoing_evals.resize(2 * incoming_qps.size());

      for (unsigned int qp = 0; qp < incoming_qps.size(); qp++)
      {
        const Point & qpt = incoming_qps[qp];
        outgoing_evals[2 * qp] = std::numeric_limits<Real>::max();
        for (unsigned int i_local_from = 0; i_local_from < froms_per_proc[processor_id()];
             i_local_from++)
        {
          MooseVariableFEBase & from_var = _from_vars[i_local_from];
          System & from_sys = from_var.sys().system();
          unsigned int from_sys_num = from_sys.number();
          unsigned int from_var_num = from_sys.variable_number(from_var.name());

          for (unsigned int i_node = 0; i_node < local_entities[i_local_from].size(); i_node++)
          {
            // Compute distance between the current incoming_qp to local node i_node.
            Real current_distance =
                (qpt - local_entities[i_local_from][i_node].first - _from_positions[i_local_from])
                    .norm();

            // If an incoming_qp is equally close to two or more local nodes, then
            // the first one we test will "win", even though any of the others could
            // also potentially be chosen instead... there's no way to decide among
            // the set of all equidistant points.
            //
            // outgoing_evals[2 * qp] is the current closest distance between a local point and
            // the incoming_qp.
            if (current_distance < outgoing_evals[2 * qp])
            {
              // Assuming LAGRANGE!
              if (local_entities[i_local_from][i_node].second->n_dofs(from_sys_num, from_var_num) >
                  0)
              {
                dof_id_type from_dof = local_entities[i_local_from][i_node].second->dof_number(
                    from_sys_num, from_var_num, 0);

                // The indexing of the outgoing_evals vector looks
                // like [(distance, value), (distance, value), ...]
                // for each incoming_qp. We only keep the value from
                // the node with the smallest distance to the
                // incoming_qp, and then we compare across all
                // processors later and pick the closest one.
                outgoing_evals[2 * qp] = current_distance;
                outgoing_evals[2 * qp + 1] = (*from_sys.solution)(from_dof);

                if (_fixed_meshes)
                {
                  // Cache the nearest nodes.
                  _cached_froms[i_proc][qp] = i_local_from;
                  _cached_dof_ids[i_proc][qp] = from_dof;
                }
              }
            }
          }
        }
      }

      if (i_proc == processor_id())
        incoming_evals[i_proc] = outgoing_evals;
      else
        _communicator.send(i_proc, outgoing_evals, send_evals[i_proc]);
    }
  }

  else // We've cached the nearest nodes.
  {
    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
    {
      std::vector<Real> & outgoing_evals = processor_outgoing_evals[i_proc];
      outgoing_evals.resize(_cached_froms[i_proc].size());

      for (unsigned int qp = 0; qp < outgoing_evals.size(); qp++)
      {
        MooseVariableFEBase & from_var = _from_problems[_cached_froms[i_proc][qp]]->getVariable(
            0,
            _from_var_name,
            Moose::VarKindType::VAR_ANY,
            Moose::VarFieldType::VAR_FIELD_STANDARD);
        System & from_sys = from_var.sys().system();
        dof_id_type from_dof = _cached_dof_ids[i_proc][qp];
        // outgoing_evals[qp] = (*from_sys.solution)(_cached_dof_ids[i_proc][qp]);
        outgoing_evals[qp] = (*from_sys.solution)(from_dof);
      }

      if (i_proc == processor_id())
        incoming_evals[i_proc] = outgoing_evals;
      else
        _communicator.send(i_proc, outgoing_evals, send_evals[i_proc]);
    }
  }

  ////////////////////
  // Gather all of the evaluations, find the nearest one for each node/element,
  // and apply the values.
  ////////////////////

  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;

    _communicator.receive(i_proc, incoming_evals[i_proc]);
  }

  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
  {
    // Loop over the master nodes and set the value of the variable
    System * to_sys = find_sys(*_to_es[i_to], _to_var_name);

    unsigned int sys_num = to_sys->number();
    unsigned int var_num = to_sys->variable_number(_to_var_name);

    NumericVector<Real> * solution = nullptr;
    switch (_direction)
    {
      case TO_MULTIAPP:
        solution = &getTransferVector(i_to, _to_var_name);
        break;
      case FROM_MULTIAPP:
        solution = to_sys->solution.get();
        break;
      default:
        mooseError("Unknown direction");
    }

    const MeshBase & to_mesh = _to_meshes[i_to]->getMesh();

    bool is_to_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

    if (is_to_nodal)
    {
      std::vector<Node *> target_local_nodes;

      if (isParamValid("target_boundary"))
      {
        BoundaryID target_bnd_id =
            _to_meshes[i_to]->getBoundaryID(getParam<BoundaryName>("target_boundary"));

        ConstBndNodeRange & bnd_nodes = *(_to_meshes[i_to])->getBoundaryNodeRange();
        for (const auto & bnode : bnd_nodes)
          if (bnode->_bnd_id == target_bnd_id && bnode->_node->processor_id() == processor_id())
            target_local_nodes.push_back(bnode->_node);
      }
      else
      {
        target_local_nodes.resize(to_mesh.n_local_nodes());
        unsigned int i = 0;
        for (auto & node : to_mesh.local_node_ptr_range())
          target_local_nodes[i++] = node;
      }

      for (const auto & node : target_local_nodes)
      {
        // Skip this node if the variable has no dofs at it.
        if (node->n_dofs(sys_num, var_num) < 1)
          continue;

        // If nothing is in the node_index_map for a given local node,
        // it will get the value 0.
        Real best_val = 0;
        if (!_neighbors_cached)
        {
          // Search through all the incoming evaluation points from
          // different processors for the one with the closest
          // point. If there are multiple values from other processors
          // which are equidistant, the first one we check will "win".
          Real min_dist = std::numeric_limits<Real>::max();
          for (unsigned int i_from = 0; i_from < incoming_evals.size(); i_from++)
          {
            std::pair<unsigned int, unsigned int> key(i_to, node->id());
            if (node_index_map[i_from].find(key) == node_index_map[i_from].end())
              continue;
            unsigned int qp_ind = node_index_map[i_from][key];
            if (incoming_evals[i_from][2 * qp_ind] >= min_dist)
              continue;

            // If we made it here, we are going set a new value and
            // distance because we found one that was closer.
            min_dist = incoming_evals[i_from][2 * qp_ind];
            best_val = incoming_evals[i_from][2 * qp_ind + 1];

            if (_fixed_meshes)
            {
              // Cache these indices.
              _cached_from_inds[node->id()] = i_from;
              _cached_qp_inds[node->id()] = qp_ind;
            }
          }
        }

        else
        {
          best_val = incoming_evals[_cached_from_inds[node->id()]][_cached_qp_inds[node->id()]];
        }

        dof_id_type dof = node->dof_number(sys_num, var_num, 0);
        solution->set(dof, best_val);
      }
    }
    else // Elemental
    {
      for (auto & elem : to_mesh.active_local_element_ptr_range())
      {
        // Skip this element if the variable has no dofs at it.
        if (elem->n_dofs(sys_num, var_num) < 1)
          continue;

        Real best_val = 0;
        if (!_neighbors_cached)
        {
          Real min_dist = std::numeric_limits<Real>::max();
          for (unsigned int i_from = 0; i_from < incoming_evals.size(); i_from++)
          {
            std::pair<unsigned int, unsigned int> key(i_to, elem->id());
            if (node_index_map[i_from].find(key) == node_index_map[i_from].end())
              continue;
            unsigned int qp_ind = node_index_map[i_from][key];
            if (incoming_evals[i_from][2 * qp_ind] >= min_dist)
              continue;
            min_dist = incoming_evals[i_from][2 * qp_ind];
            best_val = incoming_evals[i_from][2 * qp_ind + 1];

            if (_fixed_meshes)
            {
              // Cache these indices.
              _cached_from_inds[elem->id()] = i_from;
              _cached_qp_inds[elem->id()] = qp_ind;
            }
          }
        }

        else
        {
          best_val = incoming_evals[_cached_from_inds[elem->id()]][_cached_qp_inds[elem->id()]];
        }

        dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
        solution->set(dof, best_val);
      }
    }
    solution->close();
    to_sys->update();
  }

  if (_fixed_meshes)
    _neighbors_cached = true;

  // Make sure all our sends succeeded.
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;
    send_qps[i_proc].wait();
    send_evals[i_proc].wait();
  }

  _console << "Finished NearestNodeTransfer " << name() << std::endl;
}
Ejemplo n.º 15
0
void
MultiAppCopyTransfer::execute()
{
  _console << "Beginning CopyTransfer " << name() << std::endl;

  switch (_direction)
  {
    case TO_MULTIAPP:
    {
      FEProblem & from_problem = _multi_app->problem();
      MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);

      MeshBase * from_mesh = NULL;

      from_mesh = &from_problem.mesh().getMesh();

      SystemBase & from_system_base = from_var.sys();

      System & from_sys = from_system_base.system();
      unsigned int from_sys_num = from_sys.number();

      // Only works with a serialized mesh to transfer from!
      mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppCopyTransfer only works with ReplicatedMesh!");

      unsigned int from_var_num = from_sys.variable_number(from_var.name());

      //Create a serialized version of the solution vector
//      NumericVector<Number> * serialized_solution = NumericVector<Number>::build(from_sys.comm()).release();
//      serialized_solution->init(from_sys.n_dofs(), false, SERIAL);

      // Need to pull down a full copy of this vector on every processor so we can get values in parallel
//      from_sys.solution->localize(*serialized_solution);

      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (_multi_app->hasLocalApp(i))
        {
          MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

          // Loop over the master nodes and set the value of the variable
          System * to_sys = find_sys(_multi_app->appProblem(i).es(), _to_var_name);

          unsigned int sys_num = to_sys->number();
          unsigned int var_num = to_sys->variable_number(_to_var_name);

          NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);

          MeshBase * mesh = NULL;

          mesh = &_multi_app->appProblem(i).mesh().getMesh();

          bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

          if (is_nodal)
          {
            MeshBase::const_node_iterator node_it = mesh->local_nodes_begin();
            MeshBase::const_node_iterator node_end = mesh->local_nodes_end();

            for (; node_it != node_end; ++node_it)
            {
              Node * node = *node_it;
              unsigned int node_id = node->id();

              if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
              {
                // The zero only works for LAGRANGE!
                dof_id_type dof = node->dof_number(sys_num, var_num, 0);

                // Swap back
                Moose::swapLibMeshComm(swapped);

                Node * from_node = from_mesh->node_ptr(node_id);

                // Assuming LAGRANGE!
                dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);
                //Real from_value = (*serialized_solution)(from_dof);
                Real from_value = (*from_sys.solution)(from_dof);

                // Swap again
                swapped = Moose::swapLibMeshComm(_multi_app->comm());

                solution.set(dof, from_value);
              }
            }
          }
          else // Elemental
          {
            mooseError("MultiAppCopyTransfer can only be used on nodal variables");
          }

          solution.close();
          to_sys->update();

          // Swap back
          Moose::swapLibMeshComm(swapped);
        }
      }

//      delete serialized_solution;

      break;
    }
    case FROM_MULTIAPP:
    {
      FEProblem & to_problem = _multi_app->problem();
      MooseVariable & to_var = to_problem.getVariable(0, _to_var_name);
      SystemBase & to_system_base = to_var.sys();

      System & to_sys = to_system_base.system();

      NumericVector<Real> & to_solution = *to_sys.solution;

      unsigned int to_sys_num = to_sys.number();

      // Only works with a serialized mesh to transfer to!
      mooseAssert(to_sys.get_mesh().is_serial(), "MultiAppCopyTransfer only works with ReplicatedMesh!");

      unsigned int to_var_num = to_sys.variable_number(to_var.name());

      MeshBase * to_mesh = NULL;

      to_mesh = &to_problem.mesh().getMesh();

      bool is_nodal = to_sys.variable_type(to_var_num) == FEType();

      for (unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (!_multi_app->hasLocalApp(i))
          continue;

        MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

        FEProblem & from_problem = _multi_app->appProblem(i);
        MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
        SystemBase & from_system_base = from_var.sys();

        System & from_sys = from_system_base.system();

        unsigned int from_sys_num = from_sys.number();

        unsigned int from_var_num = from_sys.variable_number(from_var.name());

        // Only works with a serialized mesh to transfer from!
        mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppCopyTransfer only works with ReplicatedMesh!");

        //Create a serialized version of the solution vector
//        NumericVector<Number> * serialized_solution = NumericVector<Number>::build(from_sys.comm()).release();
//        serialized_solution->init(from_sys.n_dofs(), false, SERIAL);

        // Need to pull down a full copy of this vector on every processor so we can get values in parallel
//        from_sys.solution->localize(*serialized_solution);


        MeshBase * from_mesh = &from_problem.mesh().getMesh();

        Moose::swapLibMeshComm(swapped);

        if (is_nodal)
        {
          MeshBase::const_node_iterator to_node_it = to_mesh->local_nodes_begin();
          MeshBase::const_node_iterator to_node_end = to_mesh->local_nodes_end();

          for (; to_node_it != to_node_end; ++to_node_it)
          {
            Node * to_node = *to_node_it;
            unsigned int to_node_id = to_node->id();

            // The zero only works for LAGRANGE!
            dof_id_type to_dof = to_node->dof_number(to_sys_num, to_var_num, 0);

            MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

            Node * from_node = from_mesh->node_ptr(to_node_id);

            // Assuming LAGRANGE!
            dof_id_type from_dof = from_node->dof_number(from_sys_num, from_var_num, 0);
            //Real from_value = (*serialized_solution)(from_dof);
            Real from_value = (*from_sys.solution)(from_dof);

            // Swap back
            Moose::swapLibMeshComm(swapped);

            to_solution.set(to_dof, from_value);
          }
        }
        else // Elemental
        {
          mooseError("MultiAppCopyTransfer can only be used on nodal variables");
        }

//        delete serialized_solution;
      }

      to_solution.close();
      to_sys.update();

      break;
    }
  }

  _console << "Finished CopyTransfer " << name() << std::endl;
}
Ejemplo n.º 16
0
void
MultiAppNearestNodeTransfer::execute()
{
  _console << "Beginning NearestNodeTransfer " << name() << std::endl;

  getAppInfo();

  // Get the bounding boxes for the "from" domains.
  std::vector<BoundingBox> bboxes = getFromBoundingBoxes();

  // Figure out how many "from" domains each processor owns.
  std::vector<unsigned int> froms_per_proc = getFromsPerProc();

  ////////////////////
  // For every point in the local "to" domain, figure out which "from" domains
  // might contain it's nearest neighbor, and send that point to the processors
  // that own those "from" domains.
  //
  // How do we know which "from" domains might contain the nearest neighbor, you
  // ask?  Well, consider two "from" domains, A and B.  If every point in A is
  // closer than every point in B, then we know that B cannot possibly contain
  // the nearest neighbor.  Hence, we'll only check A for the nearest neighbor.
  // We'll use the functions bboxMaxDistance and bboxMinDistance to figure out
  // if every point in A is closer than every point in B.
  ////////////////////

  // outgoing_qps = nodes/centroids we'll send to other processors.
  std::vector<std::vector<Point>> outgoing_qps(n_processors());
  // When we get results back, node_index_map will tell us which results go with
  // which points
  std::vector<std::map<std::pair<unsigned int, unsigned int>, unsigned int>> node_index_map(
      n_processors());

  if (!_neighbors_cached)
  {
    for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
    {
      System * to_sys = find_sys(*_to_es[i_to], _to_var_name);
      unsigned int sys_num = to_sys->number();
      unsigned int var_num = to_sys->variable_number(_to_var_name);
      MeshBase * to_mesh = &_to_meshes[i_to]->getMesh();
      bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

      if (is_nodal)
      {
        std::vector<Node *> target_local_nodes;

        if (isParamValid("target_boundary"))
        {
          BoundaryID target_bnd_id =
              _to_meshes[i_to]->getBoundaryID(getParam<BoundaryName>("target_boundary"));

          ConstBndNodeRange & bnd_nodes = *(_to_meshes[i_to])->getBoundaryNodeRange();
          for (const auto & bnode : bnd_nodes)
            if (bnode->_bnd_id == target_bnd_id && bnode->_node->processor_id() == processor_id())
              target_local_nodes.push_back(bnode->_node);
        }
        else
        {
          target_local_nodes.resize(to_mesh->n_local_nodes());
          unsigned int i = 0;
          for (auto & node : to_mesh->local_node_ptr_range())
            target_local_nodes[i++] = node;
        }

        for (const auto & node : target_local_nodes)
        {
          // Skip this node if the variable has no dofs at it.
          if (node->n_dofs(sys_num, var_num) < 1)
            continue;

          // Find which bboxes might have the nearest node to this point.
          Real nearest_max_distance = std::numeric_limits<Real>::max();
          for (const auto & bbox : bboxes)
          {
            Real distance = bboxMaxDistance(*node, bbox);
            if (distance < nearest_max_distance)
              nearest_max_distance = distance;
          }

          unsigned int from0 = 0;
          for (processor_id_type i_proc = 0; i_proc < n_processors();
               from0 += froms_per_proc[i_proc], i_proc++)
          {
            bool qp_found = false;
            for (unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && !qp_found;
                 i_from++)
            {
              Real distance = bboxMinDistance(*node, bboxes[i_from]);
              if (distance < nearest_max_distance || bboxes[i_from].contains_point(*node))
              {
                std::pair<unsigned int, unsigned int> key(i_to, node->id());
                node_index_map[i_proc][key] = outgoing_qps[i_proc].size();
                outgoing_qps[i_proc].push_back(*node + _to_positions[i_to]);
                qp_found = true;
              }
            }
          }
        }
      }
      else // Elemental
      {
        for (auto & elem : as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
        {
          Point centroid = elem->centroid();

          // Skip this element if the variable has no dofs at it.
          if (elem->n_dofs(sys_num, var_num) < 1)
            continue;

          // Find which bboxes might have the nearest node to this point.
          Real nearest_max_distance = std::numeric_limits<Real>::max();
          for (const auto & bbox : bboxes)
          {
            Real distance = bboxMaxDistance(centroid, bbox);
            if (distance < nearest_max_distance)
              nearest_max_distance = distance;
          }

          unsigned int from0 = 0;
          for (processor_id_type i_proc = 0; i_proc < n_processors();
               from0 += froms_per_proc[i_proc], i_proc++)
          {
            bool qp_found = false;
            for (unsigned int i_from = from0; i_from < from0 + froms_per_proc[i_proc] && !qp_found;
                 i_from++)
            {
              Real distance = bboxMinDistance(centroid, bboxes[i_from]);
              if (distance < nearest_max_distance || bboxes[i_from].contains_point(centroid))
              {
                std::pair<unsigned int, unsigned int> key(i_to, elem->id());
                node_index_map[i_proc][key] = outgoing_qps[i_proc].size();
                outgoing_qps[i_proc].push_back(centroid + _to_positions[i_to]);
                qp_found = true;
              }
            }
          }
        }
      }
    }
  }

  ////////////////////
  // Send local node/centroid positions off to the other processors and take
  // care of points sent to this processor.  We'll need to check the points
  // against all of the "from" domains that this processor owns.  For each
  // point, we'll find the nearest node, then we'll send the value at that node
  // and the distance between the node and the point back to the processor that
  // requested that point.
  ////////////////////

  std::vector<std::vector<Real>> incoming_evals(n_processors());
  std::vector<Parallel::Request> send_qps(n_processors());
  std::vector<Parallel::Request> send_evals(n_processors());

  // Create these here so that they live the entire life of this function
  // and are NOT reused per processor.
  std::vector<std::vector<Real>> processor_outgoing_evals(n_processors());

  if (!_neighbors_cached)
  {
    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
    {
      if (i_proc == processor_id())
        continue;
      _communicator.send(i_proc, outgoing_qps[i_proc], send_qps[i_proc]);
    }

    // Build an array of pointers to all of this processor's local nodes.  We
    // need to do this to avoid the expense of using LibMesh iterators.  This
    // step also takes care of limiting the search to boundary nodes, if
    // applicable.
    std::vector<std::vector<Node *>> local_nodes(froms_per_proc[processor_id()]);
    for (unsigned int i = 0; i < froms_per_proc[processor_id()]; i++)
    {
      getLocalNodes(_from_meshes[i], local_nodes[i]);
    }

    if (_fixed_meshes)
    {
      _cached_froms.resize(n_processors());
      _cached_dof_ids.resize(n_processors());
    }

    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
    {
      std::vector<Point> incoming_qps;
      if (i_proc == processor_id())
        incoming_qps = outgoing_qps[i_proc];
      else
        _communicator.receive(i_proc, incoming_qps);

      if (_fixed_meshes)
      {
        _cached_froms[i_proc].resize(incoming_qps.size());
        _cached_dof_ids[i_proc].resize(incoming_qps.size());
      }

      std::vector<Real> & outgoing_evals = processor_outgoing_evals[i_proc];
      outgoing_evals.resize(2 * incoming_qps.size());

      for (unsigned int qp = 0; qp < incoming_qps.size(); qp++)
      {
        Point qpt = incoming_qps[qp];
        outgoing_evals[2 * qp] = std::numeric_limits<Real>::max();
        for (unsigned int i_local_from = 0; i_local_from < froms_per_proc[processor_id()];
             i_local_from++)
        {
          MooseVariableFEBase & from_var =
              _from_problems[i_local_from]->getVariable(0,
                                                        _from_var_name,
                                                        Moose::VarKindType::VAR_ANY,
                                                        Moose::VarFieldType::VAR_FIELD_STANDARD);
          System & from_sys = from_var.sys().system();
          unsigned int from_sys_num = from_sys.number();
          unsigned int from_var_num = from_sys.variable_number(from_var.name());

          for (unsigned int i_node = 0; i_node < local_nodes[i_local_from].size(); i_node++)
          {
            Real current_distance =
                (qpt - *(local_nodes[i_local_from][i_node]) - _from_positions[i_local_from]).norm();
            if (current_distance < outgoing_evals[2 * qp])
            {
              // Assuming LAGRANGE!
              if (local_nodes[i_local_from][i_node]->n_dofs(from_sys_num, from_var_num) > 0)
              {
                dof_id_type from_dof =
                    local_nodes[i_local_from][i_node]->dof_number(from_sys_num, from_var_num, 0);

                outgoing_evals[2 * qp] = current_distance;
                outgoing_evals[2 * qp + 1] = (*from_sys.solution)(from_dof);

                if (_fixed_meshes)
                {
                  // Cache the nearest nodes.
                  _cached_froms[i_proc][qp] = i_local_from;
                  _cached_dof_ids[i_proc][qp] = from_dof;
                }
              }
            }
          }
        }
      }

      if (i_proc == processor_id())
        incoming_evals[i_proc] = outgoing_evals;
      else
        _communicator.send(i_proc, outgoing_evals, send_evals[i_proc]);
    }
  }

  else // We've cached the nearest nodes.
  {
    for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
    {
      std::vector<Real> & outgoing_evals = processor_outgoing_evals[i_proc];
      outgoing_evals.resize(_cached_froms[i_proc].size());

      for (unsigned int qp = 0; qp < outgoing_evals.size(); qp++)
      {
        MooseVariableFEBase & from_var = _from_problems[_cached_froms[i_proc][qp]]->getVariable(
            0,
            _from_var_name,
            Moose::VarKindType::VAR_ANY,
            Moose::VarFieldType::VAR_FIELD_STANDARD);
        System & from_sys = from_var.sys().system();
        dof_id_type from_dof = _cached_dof_ids[i_proc][qp];
        // outgoing_evals[qp] = (*from_sys.solution)(_cached_dof_ids[i_proc][qp]);
        outgoing_evals[qp] = (*from_sys.solution)(from_dof);
      }

      if (i_proc == processor_id())
        incoming_evals[i_proc] = outgoing_evals;
      else
        _communicator.send(i_proc, outgoing_evals, send_evals[i_proc]);
    }
  }

  ////////////////////
  // Gather all of the evaluations, find the nearest one for each node/element,
  // and apply the values.
  ////////////////////

  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;

    _communicator.receive(i_proc, incoming_evals[i_proc]);
  }

  for (unsigned int i_to = 0; i_to < _to_problems.size(); i_to++)
  {
    // Loop over the master nodes and set the value of the variable
    System * to_sys = find_sys(*_to_es[i_to], _to_var_name);

    unsigned int sys_num = to_sys->number();
    unsigned int var_num = to_sys->variable_number(_to_var_name);

    NumericVector<Real> * solution = nullptr;
    switch (_direction)
    {
      case TO_MULTIAPP:
        solution = &getTransferVector(i_to, _to_var_name);
        break;
      case FROM_MULTIAPP:
        solution = to_sys->solution.get();
        break;
      default:
        mooseError("Unknown direction");
    }

    MeshBase * to_mesh = &_to_meshes[i_to]->getMesh();

    bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

    if (is_nodal)
    {
      std::vector<Node *> target_local_nodes;

      if (isParamValid("target_boundary"))
      {
        BoundaryID target_bnd_id =
            _to_meshes[i_to]->getBoundaryID(getParam<BoundaryName>("target_boundary"));

        ConstBndNodeRange & bnd_nodes = *(_to_meshes[i_to])->getBoundaryNodeRange();
        for (const auto & bnode : bnd_nodes)
          if (bnode->_bnd_id == target_bnd_id && bnode->_node->processor_id() == processor_id())
            target_local_nodes.push_back(bnode->_node);
      }
      else
      {
        target_local_nodes.resize(to_mesh->n_local_nodes());
        unsigned int i = 0;
        for (auto & node : to_mesh->local_node_ptr_range())
          target_local_nodes[i++] = node;
      }

      for (const auto & node : target_local_nodes)
      {
        // Skip this node if the variable has no dofs at it.
        if (node->n_dofs(sys_num, var_num) < 1)
          continue;

        Real best_val = 0;
        if (!_neighbors_cached)
        {
          Real min_dist = std::numeric_limits<Real>::max();
          for (unsigned int i_from = 0; i_from < incoming_evals.size(); i_from++)
          {
            std::pair<unsigned int, unsigned int> key(i_to, node->id());
            if (node_index_map[i_from].find(key) == node_index_map[i_from].end())
              continue;
            unsigned int qp_ind = node_index_map[i_from][key];
            if (incoming_evals[i_from][2 * qp_ind] >= min_dist)
              continue;
            min_dist = incoming_evals[i_from][2 * qp_ind];
            best_val = incoming_evals[i_from][2 * qp_ind + 1];

            if (_fixed_meshes)
            {
              // Cache these indices.
              _cached_from_inds[node->id()] = i_from;
              _cached_qp_inds[node->id()] = qp_ind;
            }
          }
        }

        else
        {
          best_val = incoming_evals[_cached_from_inds[node->id()]][_cached_qp_inds[node->id()]];
        }

        dof_id_type dof = node->dof_number(sys_num, var_num, 0);
        solution->set(dof, best_val);
      }
    }
    else // Elemental
    {
      for (auto & elem : as_range(to_mesh->local_elements_begin(), to_mesh->local_elements_end()))
      {
        // Skip this element if the variable has no dofs at it.
        if (elem->n_dofs(sys_num, var_num) < 1)
          continue;

        Real best_val = 0;
        if (!_neighbors_cached)
        {
          Real min_dist = std::numeric_limits<Real>::max();
          for (unsigned int i_from = 0; i_from < incoming_evals.size(); i_from++)
          {
            std::pair<unsigned int, unsigned int> key(i_to, elem->id());
            if (node_index_map[i_from].find(key) == node_index_map[i_from].end())
              continue;
            unsigned int qp_ind = node_index_map[i_from][key];
            if (incoming_evals[i_from][2 * qp_ind] >= min_dist)
              continue;
            min_dist = incoming_evals[i_from][2 * qp_ind];
            best_val = incoming_evals[i_from][2 * qp_ind + 1];

            if (_fixed_meshes)
            {
              // Cache these indices.
              _cached_from_inds[elem->id()] = i_from;
              _cached_qp_inds[elem->id()] = qp_ind;
            }
          }
        }

        else
        {
          best_val = incoming_evals[_cached_from_inds[elem->id()]][_cached_qp_inds[elem->id()]];
        }

        dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
        solution->set(dof, best_val);
      }
    }
    solution->close();
    to_sys->update();
  }

  if (_fixed_meshes)
    _neighbors_cached = true;

  // Make sure all our sends succeeded.
  for (processor_id_type i_proc = 0; i_proc < n_processors(); i_proc++)
  {
    if (i_proc == processor_id())
      continue;
    send_qps[i_proc].wait();
    send_evals[i_proc].wait();
  }

  _console << "Finished NearestNodeTransfer " << name() << std::endl;
}
Ejemplo n.º 17
0
void
MultiAppNearestNodeTransfer::execute()
{
  Moose::out << "Beginning NearestNodeTransfer " << _name << std::endl;

  switch(_direction)
  {
    case TO_MULTIAPP:
    {
      FEProblem & from_problem = *_multi_app->problem();
      MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);

      MeshBase * from_mesh = NULL;

      if (_displaced_source_mesh && from_problem.getDisplacedProblem())
      {
        mooseError("Cannot use a NearestNode transfer from a displaced mesh to a MultiApp!");
        from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh();
      }
      else
        from_mesh = &from_problem.mesh().getMesh();

      SystemBase & from_system_base = from_var.sys();

      System & from_sys = from_system_base.system();
      unsigned int from_sys_num = from_sys.number();

      // Only works with a serialized mesh to transfer from!
      mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppNearestNodeTransfer only works with SerialMesh!");

      unsigned int from_var_num = from_sys.variable_number(from_var.name());

      // EquationSystems & from_es = from_sys.get_equation_systems();

      //Create a serialized version of the solution vector
      NumericVector<Number> * serialized_solution = NumericVector<Number>::build().release();
      serialized_solution->init(from_sys.n_dofs(), false, SERIAL);

      // Need to pull down a full copy of this vector on every processor so we can get values in parallel
      from_sys.solution->localize(*serialized_solution);

      for(unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (_multi_app->hasLocalApp(i))
        {
          MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

          // Loop over the master nodes and set the value of the variable
          System * to_sys = find_sys(_multi_app->appProblem(i)->es(), _to_var_name);

          if (!to_sys)
            mooseError("Cannot find variable "<<_to_var_name<<" for "<<_name<<" Transfer");

          unsigned int sys_num = to_sys->number();
          unsigned int var_num = to_sys->variable_number(_to_var_name);

          NumericVector<Real> & solution = _multi_app->appTransferVector(i, _to_var_name);

          MeshBase * mesh = NULL;

          if (_displaced_target_mesh && _multi_app->appProblem(i)->getDisplacedProblem())
            mesh = &_multi_app->appProblem(i)->getDisplacedProblem()->mesh().getMesh();
          else
            mesh = &_multi_app->appProblem(i)->mesh().getMesh();

          bool is_nodal = to_sys->variable_type(var_num).family == LAGRANGE;

          if (is_nodal)
          {
            MeshBase::const_node_iterator node_it = mesh->local_nodes_begin();
            MeshBase::const_node_iterator node_end = mesh->local_nodes_end();

            for(; node_it != node_end; ++node_it)
            {
              Node * node = *node_it;

              Point actual_position = *node+_multi_app->position(i);

              if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
              {
                // The zero only works for LAGRANGE!
                dof_id_type dof = node->dof_number(sys_num, var_num, 0);

                // Swap back
                Moose::swapLibMeshComm(swapped);

                Real distance = 0; // Just to satisfy the last argument

                MeshBase::const_node_iterator from_nodes_begin = from_mesh->nodes_begin();
                MeshBase::const_node_iterator from_nodes_end   = from_mesh->nodes_end();

                Node * nearest_node = NULL;

                if (_fixed_meshes)
                {
                  if (_node_map.find(node->id()) == _node_map.end())  // Haven't cached it yet
                  {
                    nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end);
                    _node_map[node->id()] = nearest_node;
                    _distance_map[node->id()] = distance;
                  }
                  else
                  {
                    nearest_node = _node_map[node->id()];
                    //distance = _distance_map[node->id()];
                  }
                }
                else
                  nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end);

                // Assuming LAGRANGE!
                dof_id_type from_dof = nearest_node->dof_number(from_sys_num, from_var_num, 0);
                Real from_value = (*serialized_solution)(from_dof);

                // Swap again
                swapped = Moose::swapLibMeshComm(_multi_app->comm());

                solution.set(dof, from_value);
              }
            }
          }
          else // Elemental
          {
            MeshBase::const_element_iterator elem_it = mesh->local_elements_begin();
            MeshBase::const_element_iterator elem_end = mesh->local_elements_end();

            for(; elem_it != elem_end; ++elem_it)
            {
              Elem * elem = *elem_it;

              Point centroid = elem->centroid();
              Point actual_position = centroid+_multi_app->position(i);

              if (elem->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this elem
              {
                // The zero only works for LAGRANGE!
                dof_id_type dof = elem->dof_number(sys_num, var_num, 0);

                // Swap back
                Moose::swapLibMeshComm(swapped);

                Real distance = 0; // Just to satisfy the last argument

                MeshBase::const_node_iterator from_nodes_begin = from_mesh->nodes_begin();
                MeshBase::const_node_iterator from_nodes_end   = from_mesh->nodes_end();

                Node * nearest_node = NULL;

                if (_fixed_meshes)
                {
                  if (_node_map.find(elem->id()) == _node_map.end())  // Haven't cached it yet
                  {
                    nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end);
                    _node_map[elem->id()] = nearest_node;
                    _distance_map[elem->id()] = distance;
                  }
                  else
                  {
                    nearest_node = _node_map[elem->id()];
                    //distance = _distance_map[elem->id()];
                  }
                }
                else
                  nearest_node = getNearestNode(actual_position, distance, from_nodes_begin, from_nodes_end);

                // Assuming LAGRANGE!
                dof_id_type from_dof = nearest_node->dof_number(from_sys_num, from_var_num, 0);
                Real from_value = (*serialized_solution)(from_dof);

                // Swap again
                swapped = Moose::swapLibMeshComm(_multi_app->comm());

                solution.set(dof, from_value);
              }
            }
          }

          solution.close();
          to_sys->update();

          // Swap back
          Moose::swapLibMeshComm(swapped);
        }
      }

      delete serialized_solution;

      break;
    }
    case FROM_MULTIAPP:
    {
      FEProblem & to_problem = *_multi_app->problem();
      MooseVariable & to_var = to_problem.getVariable(0, _to_var_name);
      SystemBase & to_system_base = to_var.sys();

      System & to_sys = to_system_base.system();

      NumericVector<Real> & to_solution = *to_sys.solution;

      unsigned int to_sys_num = to_sys.number();

      // Only works with a serialized mesh to transfer to!
      mooseAssert(to_sys.get_mesh().is_serial(), "MultiAppNearestNodeTransfer only works with SerialMesh!");

      unsigned int to_var_num = to_sys.variable_number(to_var.name());

      // EquationSystems & to_es = to_sys.get_equation_systems();

      MeshBase * to_mesh = NULL;

      if (_displaced_target_mesh && to_problem.getDisplacedProblem())
        to_mesh = &to_problem.getDisplacedProblem()->mesh().getMesh();
      else
        to_mesh = &to_problem.mesh().getMesh();

      bool is_nodal = to_sys.variable_type(to_var_num) == FEType();

      dof_id_type n_nodes = to_mesh->n_nodes();
      dof_id_type n_elems = to_mesh->n_elem();

      ///// All of the following are indexed off to_node->id() or to_elem->id() /////

      // Minimum distances from each node in the "to" mesh to a node in
      std::vector<Real> min_distances;

      // The node ids in the "from" mesh that this processor has found to be the minimum distances to the "to" nodes
      std::vector<dof_id_type> min_nodes;

      // After the call to maxloc() this will tell us which processor actually has the minimum
      std::vector<unsigned int> min_procs;

      // The global multiapp ID that this processor found had the minimum distance node in it.
      std::vector<unsigned int> min_apps;


      if (is_nodal)
      {
        min_distances.resize(n_nodes, std::numeric_limits<Real>::max());
        min_nodes.resize(n_nodes);
        min_procs.resize(n_nodes);
        min_apps.resize(n_nodes);
      }
      else
      {
        min_distances.resize(n_elems, std::numeric_limits<Real>::max());
        min_nodes.resize(n_elems);
        min_procs.resize(n_elems);
        min_apps.resize(n_elems);
      }

      for(unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
      {
        if (!_multi_app->hasLocalApp(i))
          continue;

        MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

        FEProblem & from_problem = *_multi_app->appProblem(i);
        MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
        SystemBase & from_system_base = from_var.sys();

        System & from_sys = from_system_base.system();

        // Only works with a serialized mesh to transfer from!
        mooseAssert(from_sys.get_mesh().is_serial(), "MultiAppNearestNodeTransfer only works with SerialMesh!");

        // unsigned int from_var_num = from_sys.variable_number(from_var.name());

        // EquationSystems & from_es = from_sys.get_equation_systems();

        MeshBase * from_mesh = NULL;

        if (_displaced_source_mesh && from_problem.getDisplacedProblem())
          from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh();
        else
          from_mesh = &from_problem.mesh().getMesh();

        MeshTools::BoundingBox app_box = MeshTools::processor_bounding_box(*from_mesh, libMesh::processor_id());
        Point app_position = _multi_app->position(i);

        Moose::swapLibMeshComm(swapped);

        if (is_nodal)
        {
          MeshBase::const_node_iterator to_node_it = to_mesh->nodes_begin();
          MeshBase::const_node_iterator to_node_end = to_mesh->nodes_end();

          for(; to_node_it != to_node_end; ++to_node_it)
          {
            Node * to_node = *to_node_it;
            unsigned int to_node_id = to_node->id();

            Real current_distance = 0;

            MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

            MeshBase::const_node_iterator from_nodes_begin = from_mesh->local_nodes_begin();
            MeshBase::const_node_iterator from_nodes_end   = from_mesh->local_nodes_end();

            Node * nearest_node = NULL;

            if (_fixed_meshes)
            {
              if (_node_map.find(to_node->id()) == _node_map.end())  // Haven't cached it yet
              {
                nearest_node = getNearestNode(*to_node-app_position, current_distance, from_nodes_begin, from_nodes_end);
                _node_map[to_node->id()] = nearest_node;
                _distance_map[to_node->id()] = current_distance;
              }
              else
              {
                nearest_node = _node_map[to_node->id()];
                current_distance = _distance_map[to_node->id()];
              }
            }
            else
              nearest_node = getNearestNode(*to_node-app_position, current_distance, from_nodes_begin, from_nodes_end);

            Moose::swapLibMeshComm(swapped);

            // TODO: Logic bug when we are using caching.  "current_distance" is set by a call to getNearestNode which is
            // skipped in that case.  We shouldn't be relying on it or stuffing it in another data structure
            if (current_distance < min_distances[to_node->id()])
            {
              min_distances[to_node_id] = current_distance;
              min_nodes[to_node_id] = nearest_node->id();
              min_apps[to_node_id] = i;
            }
          }
        }
        else // Elemental
        {
          MeshBase::const_element_iterator to_elem_it = to_mesh->elements_begin();
          MeshBase::const_element_iterator to_elem_end = to_mesh->elements_end();

          for(; to_elem_it != to_elem_end; ++to_elem_it)
          {
            Elem * to_elem = *to_elem_it;
            unsigned int to_elem_id = to_elem->id();

            Point actual_position = to_elem->centroid()-app_position;

            Real current_distance = 0;

            MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

            MeshBase::const_node_iterator from_nodes_begin = from_mesh->local_nodes_begin();
            MeshBase::const_node_iterator from_nodes_end   = from_mesh->local_nodes_end();

            Node * nearest_node = NULL;

            if (_fixed_meshes)
            {
              if (_node_map.find(to_elem->id()) == _node_map.end())  // Haven't cached it yet
              {
                nearest_node = getNearestNode(actual_position, current_distance, from_nodes_begin, from_nodes_end);
                _node_map[to_elem->id()] = nearest_node;
                _distance_map[to_elem->id()] = current_distance;
              }
              else
              {
                nearest_node = _node_map[to_elem->id()];
                current_distance = _distance_map[to_elem->id()];
              }
            }
            else
              nearest_node = getNearestNode(actual_position, current_distance, from_nodes_begin, from_nodes_end);

            Moose::swapLibMeshComm(swapped);

            // TODO: Logic bug when we are using caching.  "current_distance" is set by a call to getNearestNode which is
            // skipped in that case.  We shouldn't be relying on it or stuffing it in another data structure
            if (current_distance < min_distances[to_elem->id()])
            {
              min_distances[to_elem_id] = current_distance;
              min_nodes[to_elem_id] = nearest_node->id();
              min_apps[to_elem_id] = i;
            }
          }
        }
      }

/*
      // We're going to need serialized solution vectors for each app
      // We could try to only do it for the apps that have mins in them...
      // but it's tough because this is a collective operation... so that would have to be coordinated
      std::vector<NumericVector<Number> *> serialized_from_solutions(_multi_app->numGlobalApps());

      if (_multi_app->hasApp())
      {
        // Swap
        MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

        for(unsigned int i=0; i<_multi_app->numGlobalApps(); i++)
        {
          if (!_multi_app->hasLocalApp(i))
            continue;

          FEProblem & from_problem = *_multi_app->appProblem(i);
          MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
          SystemBase & from_system_base = from_var.sys();

          System & from_sys = from_system_base.system();

          //Create a serialized version of the solution vector
          serialized_from_solutions[i] = NumericVector<Number>::build().release();
          serialized_from_solutions[i]->init(from_sys.n_dofs(), false, SERIAL);

          // Need to pull down a full copy of this vector on every processor so we can get values in parallel
          from_sys.solution->localize(*serialized_from_solutions[i]);
        }

        // Swap back
        Moose::swapLibMeshComm(swapped);
      }
*/

      // We've found the nearest nodes for this processor.  We need to see which processor _actually_ found the nearest though
      Parallel::minloc(min_distances, min_procs);

      // Now loop through min_procs and see if _this_ processor had the actual minimum for any nodes.
      // If it did then we're going to go get the value from that nearest node and transfer its value
      processor_id_type proc_id = libMesh::processor_id();

      for(unsigned int j=0; j<min_procs.size(); j++)
      {
        if (min_procs[j] == proc_id) // This means that this processor really did find the minumum so we need to transfer the value
        {
          // The zero only works for LAGRANGE!
          dof_id_type to_dof = 0;

          if (is_nodal)
          {
            Node & to_node = to_mesh->node(j);
            to_dof = to_node.dof_number(to_sys_num, to_var_num, 0);
          }
          else
          {
            Elem & to_elem = *to_mesh->elem(j);
            to_dof = to_elem.dof_number(to_sys_num, to_var_num, 0);
          }

          // The app that has the nearest node in it
          unsigned int from_app_num = min_apps[j];

          mooseAssert(_multi_app->hasLocalApp(from_app_num), "Something went very wrong!");

          // Swap
          MPI_Comm swapped = Moose::swapLibMeshComm(_multi_app->comm());

          FEProblem & from_problem = *_multi_app->appProblem(from_app_num);
          MooseVariable & from_var = from_problem.getVariable(0, _from_var_name);
          SystemBase & from_system_base = from_var.sys();

          System & from_sys = from_system_base.system();
          unsigned int from_sys_num = from_sys.number();

          unsigned int from_var_num = from_sys.variable_number(from_var.name());

          // EquationSystems & from_es = from_sys.get_equation_systems();

          MeshBase * from_mesh = NULL;

          if (_displaced_source_mesh && from_problem.getDisplacedProblem())
            from_mesh = &from_problem.getDisplacedProblem()->mesh().getMesh();
          else
            from_mesh = &from_problem.mesh().getMesh();

          Node & from_node = from_mesh->node(min_nodes[j]);

          // Assuming LAGRANGE!
          dof_id_type from_dof = from_node.dof_number(from_sys_num, from_var_num, 0);
          Real from_value = (*from_sys.solution)(from_dof);

          // Swap back
          Moose::swapLibMeshComm(swapped);

          to_solution.set(to_dof, from_value);
        }
      }

      to_solution.close();
      to_sys.update();

      break;
    }
  }

  Moose::out << "Finished NearestNodeTransfer " << _name << std::endl;
}