How to Access 'visualization postprocessor' for particle property

My code is like this:

namespace aspect
{
namespace Particle
{
namespace Property
{
MyParticle::update_particle_property (…) const
{
const Postprocess::VisualizationPostprocessors::MeltFraction &melt_fraction=
this->get_postprocess_manager().template get_matching_postprocessor<Postprocess::VisualizationPostprocessors::MeltFraction >();
// do something using ‘melt_fraction’. For example intepolate melt fraction to particle position. (I know this is not nessesary, just for simple demonstration)
}
}
}
}

And I get:“You asked Postprocess::Manager::get_matching_postprocessor() for a postprocessor of type <aspect::Postprocess::VisualizationPostprocessors::MeltFraction<2>> that could not be found in the current model. Activate this postprocessor in the input file.”, which I have already activated in the input file but get this error anyway.

The reason I want to do this is that I did some complex calculations to get a kind of field data in a user-defined VisualizationPostprocessor and I want to interpolate that value on every particle.

Hi Chester,

Thanks for posting this question to the forum.

To summarize, my understanding is that you want to use the functionality in the visualization/melt_fraction post processor when calculating a particle property, rather than repeating the same code. Is this correct?

Broadly, great to see you are trying to reuse existing code, rather than duplicating it!

You can certainly call one post processor inside a different post processor (example dynamic_topography and surface_dynamic_topography), but I’m not sure if it would work to call the relevant function in melt_fraction (evaluate_vector_field) or another similar function from a particle post processor.

There is an example evaluating the material model properties from a particle post processor, but in that case you can provide the particle position.

This was a long-winded way of saying someone else (@gassmoeller?) will need to chime in as to whether this general approach is the right way to go.

Cheers,
John

Hi Chester,
at least in principle, this is how this is supposed to work. The fact that you get an error message suggests that something does not work as expected, but it is difficult to say what specifically. Can you come up with a small testcase that illustrates your problem? An example would be a copy of your own plugin, plus a .prm file that illustrates what you are trying to do and that triggers the error.

Best
W.

Thanks a lot for your reply!
Actually what I want to is very similar to what has been done in dynamic_topography. dynamic_topography is exactly my starting point. I’m not sure why this line of code would work in dynamic_topography but not in a particle property plugin. I have provided the code example in reply to bangerth. Maybe you want to take a look at that.

Thanks a lot for your reply.
It seems I can not upload files so I just paste the code here. I hope this is not too messy to look at. And I have described what I really want to do in the code.

the plugin cc file:

#ifndef _aspect_particle_property_my_particle_h
#define _aspect_particle_property_my_particle_h

#include <aspect/simulator_access.h>
#include <aspect/particle/property/interface.h>
#include <aspect/postprocess/visualization/error_indicator.h>

namespace aspect
{
  namespace Particle
  {
    namespace Property
    {
      template <int dim>
      class MyParticle : public Interface<dim>, public ::aspect::SimulatorAccess<dim>
      {
        public:
          void
          initialize_one_particle_property (const Point<dim> &position,
                                            std::vector<double> &particle_properties) const override;

          virtual
          void
          update_particle_property (const unsigned int data_position,
                                    const Vector<double> &solution,
                                    const std::vector<Tensor<1,dim> > &gradients,
                                    typename ParticleHandler<dim>::particle_iterator &particle) const;

          UpdateTimeFlags
          need_update () const override;
          UpdateFlags
          get_needed_update_flags () const override;

          std::vector<std::pair<std::string, unsigned int> >
          get_property_information() const override;
      };
    }
  }
}
#endif

namespace aspect
{
  namespace Particle
  {
    namespace Property
    {
      template <int dim>
      void
      MyParticle<dim>::initialize_one_particle_property(const Point<dim> &position,
                                                                  std::vector<double> &data) const
      {
        data.push_back(0.0);
      }

      template <int dim>
      void
      MyParticle<dim>::update_particle_property (const unsigned int data_position,
                                                  const Vector<double> &solution,
                                                  const std::vector<Tensor<1,dim> > &gradients,
                                                  typename ParticleHandler<dim>::particle_iterator &particle) const
      {
        const Postprocess::VisualizationPostprocessors::ErrorIndicator<dim> &error_indicator =
          this->get_postprocess_manager().template get_matching_postprocessor<Postprocess::VisualizationPostprocessors::ErrorIndicator<dim> >();

        // Do anything with error_indicator, I don't really care. Or just don't do anything.
        // For example, do the following code to intepolate error indicator for every particle:
        /*
        const std::pair<std::string, Vector<float> *> error_indicator_cell_data = error_indicator->execute();
        typename parallel::distributed::Triangulation<dim>::cell_iterator found_cell;
        found_cell = particle->get_surrounding_cell(this->get_triangulation());
        data[manager.get_data_info().get_position_by_field_name("my particle")] = *error_indicator_cell_data.second(found_cell.active_cell_index());
        */

        // What I really want to do is a little bit complex than this:
        // 1st: I have already defined a properly working new way of writing visualization postprocessors in './source/postprocess/visualization.cc'
        //      which out put a field data. It is similar to DataPostprocessor in the way that it can be evaluate on every point.
        //      But it is different from DataPostprocessor in that it is not a point-wise function but needs all other cells' info to caculate it.
        // 2nd: Then I want to intepolate the value for every particle.
        //
        // But I think I'll be fine as long as I can run this simple test case.
      }

      

      template <int dim>
      UpdateTimeFlags
      MyParticle<dim>::need_update() const
      {
        return update_time_step;
      }

      template <int dim>
      UpdateFlags
      MyParticle<dim>::get_needed_update_flags() const
      {
        return update_values;
      }

      template <int dim>
      std::vector<std::pair<std::string, unsigned int>>
      MyParticle<dim>::get_property_information() const
      {
        std::vector<std::pair<std::string, unsigned int>> property_information(1, std::make_pair("my particle", 1));
        return property_information;
      }
    } // namespace Property
  }   // namespace Particle
} // namespace aspect
// explicit instantiations

namespace aspect
{
  namespace Particle
  {
    namespace Property
    {
      ASPECT_REGISTER_PARTICLE_PROPERTY(MyParticle,
                                        "my particle",
                                        "A test case.")
    }
  } // namespace Particle
} // namespace aspect

the prm input file:

set Additional shared libraries = usr_plugin/libmyParticle.so
 
set Dimension                 = 2 
set Output directory                       = testCase
set Resume computation = false
set End time                  = 500e6

set Use years in output instead of seconds = true 
set CFL number                             = 1

subsection Geometry model 
  set Model name = box 
  subsection Box 
    set X extent      = 990e3 
    set Y extent      = 660e3
    set X repetitions = 12
    set Y repetitions = 8
  end 
end 

subsection Material model 
	set Model name = simple
end 
 
subsection Gravity model 
  set Model name = vertical 
  subsection Vertical 
    set Magnitude = 9.8 
  end 
end 
 
subsection Boundary velocity model 
  set Tangential velocity boundary indicators = bottom, left, top, right
end 

subsection Initial temperature model 
  set List of model names = function 
  subsection Function 
    set Function constants = u0=0.020, kappa=31.6, T0=273, T1=1623, Lmax=9999e3, H=660e3, L=1320e3, t0=100e6, x0=0e3, w=10e3
    set Function expression = T1 - (T1-T0) * erfc((H-y)/2.0/sqrt(kappa*max(3e6, x/u0)))
  end 
end 

subsection Boundary temperature model 
  set Fixed temperature boundary indicators = top, bottom 
  set List of model names = initial temperature 
end 
 
##################### Mesh refinement ######################### 
subsection Mesh refinement 
  set Initial global refinement                = 3
  set Initial adaptive refinement              = 0
  set Time steps between mesh refinement       = 0
end 
 
##################### Postprocessing ######################## 
 
subsection Postprocess 
 
  set List of postprocessors = visualization, particles
 
  subsection Visualization 
    set List of output variables      = error indicator
    set Time between graphical output = 0
    set Output format = vtu
  end 

  subsection Particles 
    set Data output format = vtu 
    set Number of particles = 5e4

    set Load balancing strategy = add particles # remove and add particles 

    set Minimum particles per cell = 20

    set Time between data output = 0
   
    set List of particle properties = my particle
  end 
end 
 
subsection Termination criteria   
  set Checkpoint on termination = true
  set Termination criteria      = user request, end step
  set End step = 0

  subsection User request 
    set File name = terminate
  end 
end

Chester,
with your input files, I get the following error:

An error occurred in line <432> of file </home/bangerth/p/deal.II/1/projects/aspect/include/aspect/postprocess/interface.h> in function
    const PostprocessorType& aspect::Postprocess::Manager<dim>::get_matching_postprocessor() const [with PostprocessorType = aspect::Postprocess::VisualizationPostprocessors::ErrorIndicator<2>; int dim = 2]
The violated condition was: 
    has_matching_postprocessor<PostprocessorType> ()
Additional information: 
    You asked Postprocess::Manager::get_matching_postprocessor() for a
    postprocessor of type
    <aspect::Postprocess::VisualizationPostprocessors::ErrorIndicator<2>>
    that could not be found in the current model. Activate this
    postprocessor in the input file.
--------------------------------------------------------

This references the ErrorIndicator postprocessor, not the MeltFraction postprocessor you mention in your first message above.

But the real reason is that you are asking for a “visualization postprocessor” but are calling the function that queries “postprocessors”. These are different concepts – maybe that’s not quite clear from the two names, unfortunately. I believe that there is no way to query for any visualization postprocessors at the moment :frowning:

The real reasons, though, is that visualization postprocessors are only called on each cell in turn while generating graphical output. They generally don’t store any state, and they are also not called in each time step, so there is little reason to query these kinds of objects – there is nothing useful you can ask these objects.

Best
W.