Good morning everyone,


I am attempting to write a program which projects a solution vector from 
mesh A to mesh B. Both meshes are parallel distributed and have different 
geometries (the first is adaptively refined, the latter has uniform grid 
size). In addition, the solution uses Q1 elements on mesh A and is to be 
piecewise constant on mesh B.

I have attempted to use VectorTools::project() for this purpose.

-        -   I create a child of the Function class which takes in a 
solution vector and its corresponding mesh (both parallel distributed). 
This function allows the solution vector to be evaluated at any coordinate 
within the domain (and should also consider ghost elements).

-         -    I insert this as a parameter into the project() function. 
This is projected onto a non-ghosted vector, which is then assigned to a 
ghosted vector and is subsequently compressed.

The resulting vector correctly projects to some elements, however other 
*elements 
appear to be set to 0* (incorrectly). In addition, the number of elements 
that are zero and their *locations vary with the number of processors used*. 
I suspect that it may be something to do with project() not being able to 
handle ghost elements but I’m not sure. It is very possible that the 
Function used to evaluate the input vector at any coordinate is incorrect, 
i have included it in a text file below. I have tried using both 
FEFieldFunction() and later find_all_active_cells_around_point() but to no 
avail (the latter appears to return empty for these zeroed elements, even 
after I perturb the coordinate by a significant amount when no cell is 
found or use a high tolerance).

I then attempted the following crude workaround:

-            serialize the vector and triangulation

-            project them to a new serial vector using project()

-            scatter them back onto the parallel mesh

Unfortunately, this also failed. I am having difficulty copying the 
parallel mesh onto a serial one, which appears far more involved than I 
originally thought.

On a sidenote I have attempted to use interpolate() as well and was still 
unsuccessful (I encountered the same issue with elements set to 0 at the 
same locations for a given number of cores used).

Any help would be very, very much appreciated

 

Best wishes,

Daniel Rivlin

 

-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dealii+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/dealii/1fface4c-15f1-4afd-b667-2153ccfcb8c1n%40googlegroups.com.
template <int dim>
  class LinearSolutionFunction : public Function<dim>
  {
    public:
      /**
      * Constructor.
      *
      * @param dof_handler_in The DoFHandler corresponding to the linear finite 
element space.
      * @param solution_in The solution vector.
      */
      LinearSolutionFunction(const DoFHandler<dim> &dof_handler_in,
                            const LA::MPI::Vector &solution_in)
        : Function<dim>(1),
          dof_handler_linear(dof_handler_in),
          solution_linear(solution_in),
          mapping_linear(1)
      {}

      /**
      * Evaluate the solution at point p by:
      *  - Locating all active cells around p (within a given tolerance).
      *  - For each cell that is locally available (owned or ghost),
      *    compute the reference coordinate and use FEValues to perform linear 
interpolation.
      *  - Return the average value from all valid cells.
      *
      * Returns 0.0 if no valid cell is found.
      */
      virtual double value(const Point<dim> &p,
                          const unsigned int component = 0) const override
      {
        // Choose a tolerance that might need tuning.
        double tolerance = 1e-6; // Try increasing tolerance for adaptive meshes

        // Find all active cells around the point p within the specified 
tolerance.
        auto cell_and_refs = 
GridTools::find_all_active_cells_around_point(mapping_linear,
                                                                          
dof_handler_linear,
                                                                          p,
                                                                          
tolerance);
        // If no cells found, optionally try a slight perturbation.
        if (cell_and_refs.empty())
        {
          Point<dim> p_perturbed = p;
          p_perturbed[0] += 1e-5;
          p_perturbed[1] += 1e-5;
          cell_and_refs = 
GridTools::find_all_active_cells_around_point(mapping_linear,
                                                                        
dof_handler_linear,
                                                                        
p_perturbed,
                                                                        
tolerance);
          if (cell_and_refs.empty())
            return 0.0; // No cell found even after perturbation.
        }

        double result = 0.0;
        unsigned int valid_cell_count = 0;
        for (const auto &cell_and_ref : cell_and_refs)
        {
          const auto &cell = cell_and_ref.first;
          // Only use cells that are locally available (owned or ghost).
          if (!(cell->is_locally_owned() || cell->is_ghost()))
            continue;

          const auto &xi = cell_and_ref.second;
          const FiniteElement<dim> &fe = cell->get_fe();
          const unsigned int dofs_per_cell = fe.dofs_per_cell;
          std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
          cell->get_dof_indices(local_dof_indices);

          // Create a quadrature rule with the computed reference coordinate xi.
          std::vector<Point<dim>> quadrature_points(1, xi);
          Quadrature<dim> quadrature(quadrature_points);
          FEValues<dim> fe_values(mapping_linear, fe, quadrature, 
update_values);
          fe_values.reinit(cell);

          double local_value = 0.0;
          for (unsigned int i = 0; i < dofs_per_cell; ++i)
          {
            local_value += solution_linear[local_dof_indices[i]] *
                          fe_values.shape_value(i, 0);
          }
          result += local_value;
          ++valid_cell_count;
        }
        return (valid_cell_count > 0 ? result / valid_cell_count : 0.0);
      }

    private:
      const DoFHandler<dim> &dof_handler_linear;
      const LA::MPI::Vector &solution_linear;
      MappingQ<dim>          mapping_linear;
  };

Reply via email to