Ejemplo n.º 1
0
void TurbulenceStatistics::setup()
{
  if(!m_options_changed)
    return;
  m_options_changed = false;

  m_used_nodes.reset();

  Handle<mesh::Region> region = options().value< Handle<mesh::Region> >("region");
  if(is_null(region))
  {
    return;
  }

  const std::string velocity_var_name = options().value<std::string>("velocity_variable_name");
  const std::string pressure_var_name = options().value<std::string>("pressure_variable_name");
  m_velocity_field.reset();
  m_pressure_field.reset();
  
  const mesh::Mesh& mesh = common::find_parent_component<mesh::Mesh>(*region);
  Handle<mesh::Dictionary> dictionary;
  BOOST_FOREACH(const Handle<mesh::Dictionary>& dict, mesh.dictionaries())
  {
    BOOST_FOREACH(const Handle<mesh::Field>& field, dict->fields())
    {
      if(field->has_variable( velocity_var_name ))
      {
        if(is_not_null(m_velocity_field))
          throw common::SetupError(FromHere(), "There are two fields that contain the variable " + velocity_var_name );
        
        m_velocity_field = field;
        dictionary = dict;
      }
    }
  }
  
  if(is_null(m_velocity_field))
    throw common::SetupError(FromHere(), "There is no field with the variable " + velocity_var_name );
  
  m_dim = mesh.dimension();
  if(m_dim == 1)
  {
    throw common::SetupError(FromHere(), "TurbulenceStatistics are not supported in 1D");
  }
  cf3_assert(m_velocity_field->var_length(velocity_var_name) == m_dim);
  m_velocity_field_offset = m_velocity_field->var_offset( velocity_var_name );
  
  BOOST_FOREACH(const Handle<mesh::Field>& field, dictionary->fields())
  {
    if(field->has_variable( pressure_var_name ))
    { 
      m_pressure_field = field;
    }
  }
  
  if(is_null(m_pressure_field))
    throw common::SetupError(FromHere(), "There is no field with the variable " + pressure_var_name );
  
  m_pressure_field_offset = m_pressure_field->var_offset( pressure_var_name );

  const mesh::Field& coords = dictionary->coordinates();
  
  common::PE::Comm& comm = common::PE::Comm::instance();

  m_used_nodes = mesh::build_used_nodes_list(*region, *dictionary, true, false);
  const int nb_probes = m_probe_locations.size();
  std::vector<int> my_probes_found(nb_probes, 0);
  m_probe_nodes.clear();
  m_probe_indices.clear();
  const common::List<Uint>::ListT& used_nodes_list = m_used_nodes->array();
  BOOST_FOREACH(const Uint node_idx, used_nodes_list)
  {
    if(dictionary->is_ghost(node_idx))
      continue;
    for(int probe_idx = 0; probe_idx != nb_probes; ++probe_idx)
    {
      if(m_probe_locations[probe_idx].size() != m_dim)
      {
        throw common::SetupError(FromHere(), "Probe coordinates of dimension " + common::to_str(m_probe_locations[probe_idx].size()) + " do not match dimension " + common::to_str(m_dim));
      }
      if(((RealVector::Map(&coords[node_idx][0], m_dim) - m_probe_locations[probe_idx]).array().abs() < 1e-10).all())
      {
        m_probe_nodes.push_back(node_idx);
        m_probe_indices.push_back(probe_idx);
        my_probes_found[probe_idx] = 1;
      }
    }
  }

  std::vector<int> global_probes_found(nb_probes);
  if(comm.is_active() && nb_probes > 0)
  {
    comm.all_reduce(common::PE::plus(), my_probes_found, global_probes_found);
  }
  else
  {
    global_probes_found = my_probes_found;
  }
  for(int probe_idx = 0; probe_idx != nb_probes; ++probe_idx)
  {
    if(global_probes_found[probe_idx] == 0)
      throw common::SetupError(FromHere(), "Probe " + common::to_str(probe_idx) + " has no matching node");
    if(global_probes_found[probe_idx] > 1)
      throw common::SetupError(FromHere(), "Probe " + common::to_str(probe_idx) + " was found on " + common::to_str(global_probes_found[probe_idx]) + " CPUs");
  }

  const common::URI original_uri = options().value<common::URI>("file");

  // Init probe files
  m_probe_files.clear();
  const Uint nb_my_probes = m_probe_nodes.size();
  for(Uint my_idx = 0; my_idx != nb_my_probes; ++my_idx)
  {
    const Uint probe_idx = m_probe_indices[my_idx];
    std::string probe_path = (original_uri.base_path() / (original_uri.base_name() + "-probe-" + common::to_str(probe_idx) + original_uri.extension())).path();

    m_probe_files.push_back(boost::make_shared<boost::filesystem::fstream>(probe_path, std::ios_base::out));
    boost::filesystem::fstream& file = *m_probe_files.back();
    if(!file)
      throw common::FileSystemError(FromHere(), "Failed to open file " + probe_path);

    file << "# Probe data for probe " << probe_idx << " at point " << m_probe_locations[probe_idx].transpose() << "\n";
    if(m_dim == 2)
    {
      file << "# U, V, uu, vv, uv, U_rolling, V_rolling, uu_rolling, vv_rolling, uv_rolling\n";
    }
    else if(m_dim == 3)
    {
      file << "# U, V, W, uu, vv, ww, uv, uw, vw, U_rolling, V_rolling, W_rolling, uu_rolling, vv_rolling, ww_rolling, uv_rolling, uw_rolling, vw_rolling\n";
    }
  }

  // Create a field for the statistics data
  m_statistics_field = Handle<mesh::Field>(dictionary->get_child("turbulence_statistics"));
  if(is_null(m_statistics_field))
  {
    if(m_dim == 2)
    {
      m_statistics_field = dictionary->create_field("turbulence_statistics", "V[vector],uu,vv,uv,p").handle<mesh::Field>();
    }
    else if(m_dim == 3)
    {
      m_statistics_field = dictionary->create_field("turbulence_statistics", "V[vector],uu,vv,ww,uv,uw,vw,p").handle<mesh::Field>();
    }
    m_statistics_field->add_tag("turbulence_statistics");
  }

  // Reset statistics without changing m_count
  const Uint nb_accs = (2.*m_dim + m_dim-1 + m_dim-2)*m_probe_nodes.size();
  m_means.assign(nb_accs, MeanAccT());
  m_rolling_means.assign(nb_accs, RollingAccT(boost::accumulators::tag::rolling_window::window_size = options().value<Uint>("rolling_window")));
}