Пример #1
0
ElementLoop& BoundaryTerm::access_element_loop( const std::string& type_name )
{
  // ensure that the fields are present

  link_fields();

  // get the element loop or create it if does not exist

  ElementLoop::Ptr loop;
  Common::Component::Ptr cloop = get_child_ptr( "LOOP" );
  if( is_null( cloop ) )
  {
    const std::string update_vars_type =
        physical_model().get_child( RDM::Tags::update_vars() )
                        .as_type<Physics::Variables>()
                        .type();

    loop = build_component_abstract_type_reduced< FaceLoop >( "FaceLoopT<" + type_name + "," + update_vars_type + ">" , "LOOP");
    add_component(loop);
  }
  else
    loop = cloop->as_ptr_checked<ElementLoop>();


  return *loop;
}
Пример #2
0
void PrepareMesh::execute()
{
  // configuration of all solver components.
  // This component and its children should be part of it.
  solver().configure_option_recursively(sdm::Tags::solution_order(),solver().options().option(sdm::Tags::solution_order()).value<Uint>());
  solver().configure_option_recursively(sdm::Tags::mesh(),mesh().handle<Component>());
  solver().configure_option_recursively(sdm::Tags::regions(),solver().options().option(sdm::Tags::regions()).value< std::vector<URI> >());
  solver().configure_option_recursively(sdm::Tags::physical_model(),physical_model().handle<Component>());
  solver().configure_option_recursively(sdm::Tags::solver(),solver().handle<Component>());

  configure_option_recursively(sdm::Tags::solution_order(),solver().options().option(sdm::Tags::solution_order()).value<Uint>());
  configure_option_recursively(sdm::Tags::mesh(),mesh().handle<Component>());
  configure_option_recursively(sdm::Tags::regions(),solver().options().option(sdm::Tags::regions()).value< std::vector<URI> >());
  configure_option_recursively(sdm::Tags::physical_model(),physical_model().handle<Component>());
  configure_option_recursively(sdm::Tags::solver(),solver().handle<Component>());

  // execution of prepare mesh
  ActionDirector::execute();

  std::vector<URI> fields;
  fields.push_back( follow_link( solver().field_manager().get_child(sdm::Tags::solution()) )->uri() );
  solver().handle<SDSolver>()->time_stepping().post_actions().get_child("Periodic")->configure_option_recursively("fields",fields);
  solver().handle<SDSolver>()->time_stepping().post_actions().get_child("Periodic")->configure_option_recursively("file",URI("sdm_output_${time}.msh"));
}
Пример #3
0
Term& DomainDiscretization::create_term( const std::string& type,
                                         const std::string& name,
                                         const std::vector<URI>& regions )
{
  CFinfo << "Creating cell term   " << name << "(" << type << ")" << CFendl;
  Handle< Term > term = m_terms->create_component<Term>(name, type);

  if (regions.size() == 0)
    term->options().configure_option("regions", std::vector<URI>(1,mesh().topology().uri()));
  else
    term->options().configure_option("regions", regions);

  term->options().configure_option( SFDM::Tags::mesh(),           mesh().handle<Component>());
  term->options().configure_option( SFDM::Tags::solver(),         solver().handle<Component>());
  term->options().configure_option( SFDM::Tags::physical_model(), physical_model().handle<Component>());

  return *term;
}
Пример #4
0
void LSSAction::on_regions_set()
{
  if(m_implementation->m_updating) // avoid recursion
    return;

  m_implementation->m_lss = options().value< Handle<LSS::System> >("lss");
  if(is_null(m_implementation->m_lss))
    return;

  if(is_null(m_dictionary))
    return;

  m_implementation->m_updating = true;

  // Create the LSS if the mesh is set
  if(!m_loop_regions.empty() && !m_implementation->m_lss->is_created())
  {
    VariablesDescriptor& descriptor = find_component_with_tag<VariablesDescriptor>(physical_model().variable_manager(), solution_tag());

    Handle< List<Uint> > gids = m_implementation->m_lss->create_component< List<Uint> >("GIDs");
    Handle< List<Uint> > ranks = m_implementation->m_lss->create_component< List<Uint> >("Ranks");
    Handle< List<Uint> > used_node_map = m_implementation->m_lss->create_component< List<Uint> >("used_node_map");

    std::vector<Uint> node_connectivity, starting_indices;
    boost::shared_ptr< List<Uint> > used_nodes = build_sparsity(m_loop_regions, *m_dictionary, node_connectivity, starting_indices, *gids, *ranks, *used_node_map);
    add_component(used_nodes);

    // This comm pattern is valid only over the used nodes for the supplied regions
    PE::CommPattern& comm_pattern = *create_component<PE::CommPattern>("CommPattern");
    comm_pattern.insert("gid",gids->array(),false);
    comm_pattern.setup(Handle<PE::CommWrapper>(comm_pattern.get_child("gid")),ranks->array());

    CFdebug << "Creating LSS for " << starting_indices.size()-1 << " blocks with descriptor " << solution_tag() << ": " << descriptor.description() << CFendl;
    m_implementation->m_lss->create(comm_pattern, descriptor.size(), node_connectivity, starting_indices);
    CFdebug << "Finished creating LSS" << CFendl;
    configure_option_recursively(solver::Tags::regions(), options().option(solver::Tags::regions()).value());
    configure_option_recursively("lss", m_implementation->m_lss);
  }

  // Update the regions of any owned initial conditions
  BOOST_FOREACH(const Handle<Component>& ic, m_created_initial_conditions)
  {
    ic->options().set(solver::Tags::regions(), options().option(solver::Tags::regions()).value());
  }
Пример #5
0
ElementLoop& BoundaryTerm::access_element_loop( const std::string& type_name )
{
    // ensure that the fields are present

    link_fields();

    // get the element loop or create it if does not exist

    Handle< ElementLoop > loop(get_child( "LOOP" ));
    if( is_null( loop ) )
    {
        const std::string update_vars_type =
            physical_model().get_child( RDM::Tags::update_vars() )
            ->handle<physics::Variables>()
            ->type();

        loop = create_component<FaceLoop>("LOOP", "FaceLoopT<" + type_name + "," + update_vars_type + ">");
    }

    return *loop;
}
Пример #6
0
void SetupMultipleSolutions::execute()
{
  RDM::RDSolver& mysolver = solver().as_type< RDM::RDSolver >();

  /* nb_levels == rkorder */

  const Uint nb_levels = option("nb_levels").value<Uint>();

  CMesh&  mesh = *m_mesh.lock();
  CGroup& fields = mysolver.fields();

  // get the geometry field group

  Geometry& geometry = mesh.geometry();

  const std::string solution_space = mysolver.option("solution_space").value<std::string>();

  // check that the geometry belongs to the same space as selected by the user

  FieldGroup::Ptr solution_group;

  if( solution_space == geometry.space() )
    solution_group = geometry.as_ptr<FieldGroup>();
  else
  {
    // check if solution space already exists
    solution_group = find_component_ptr_with_name<FieldGroup>( mesh, RDM::Tags::solution() );
    if ( is_null(solution_group) )
    {
      boost_foreach(CEntities& elements, mesh.topology().elements_range())
          elements.create_space( RDM::Tags::solution(), "CF.Mesh.SF.SF"+elements.element_type().shape_name() + solution_space );
      solution_group = mesh.create_field_group( RDM::Tags::solution(), FieldGroup::Basis::POINT_BASED).as_ptr<FieldGroup>();
    }
    else // not null so check that space is what user wants
    {
      if( solution_space != solution_group->space() )
        throw NotImplemented( FromHere(), "Changing solution space not supported" );
    }
  }

  // construct vector of variables

  const Uint nbdofs = physical_model().neqs();

  std::string vars;
  for(Uint i = 0; i < nbdofs; ++i)
  {
   vars += "u" + to_str(i) + "[1]";
   if( i != nbdofs-1 ) vars += ",";
  }

  // configure 1st solution

  Field::Ptr solution = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::solution() );
  if ( is_null( solution ) )
  {
    solution = solution_group->create_field( RDM::Tags::solution(), vars ).as_ptr<Field>();

    solution->add_tag(Tags::solution());
  }

  // create the other solutions based on the first solution field

  std::vector< Field::Ptr > rk_steps;

  rk_steps.push_back(solution);

  for(Uint step = 1; step < nb_levels; ++step)
  {
    Field::Ptr solution_k = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::solution() + to_str(step));
    if ( is_null( solution_k ) )
    {
      std::string name = std::string(Tags::solution()) + to_str(step);
      solution_k = solution_group->create_field( name, solution->descriptor().description() ).as_ptr<Field>();
      solution_k->descriptor().prefix_variable_names("rk" + to_str(step) + "_");
      solution_k->add_tag("rksteps");
    }

    cf_assert( solution_k );
    rk_steps.push_back(solution_k);
  }

  /// @todo here we should check if space() order is correct,
  ///       if not the change space() by enriching or other appropriate action

  // configure residual

  Field::Ptr residual = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::residual());
  if ( is_null( residual ) )
  {
    residual = solution_group->create_field(Tags::residual(), solution->descriptor().description() ).as_ptr<Field>();
    residual->descriptor().prefix_variable_names("rhs_");
    residual->add_tag(Tags::residual());
  }


  // configure wave_speed

  Field::Ptr wave_speed = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::wave_speed());
  if ( is_null( wave_speed ) )
  {
    wave_speed = solution_group->create_field(Tags::wave_speed(), "ws[1]" ).as_ptr<Field>();
    wave_speed->add_tag(Tags::wave_speed());
  }


  // create links

  if( ! fields.get_child_ptr( solution->name() ) )
    fields.create_component<CLink>( solution->name() ).link_to(solution).add_tag(RDM::Tags::solution());
  if( ! fields.get_child_ptr( RDM::Tags::residual() ) )
    fields.create_component<CLink>( RDM::Tags::residual() ).link_to(residual).add_tag(RDM::Tags::residual());
  if( ! fields.get_child_ptr( RDM::Tags::wave_speed() ) )
    fields.create_component<CLink>( RDM::Tags::wave_speed() ).link_to(wave_speed).add_tag(RDM::Tags::wave_speed());

  for( Uint step = 1; step < rk_steps.size(); ++step)
  {
    if( ! fields.get_child_ptr( rk_steps[step]->name() ) )
      fields.create_component<CLink>( rk_steps[step]->name() ).link_to(solution).add_tag("rksteps");
  }


  // parallelize the solution if not yet done

  CommPattern& pattern = solution->parallelize();

  std::vector<URI> parallel_fields;
  parallel_fields.push_back( solution->uri() );

  for(Uint step = 1; step < nb_levels; ++step)
  {
    rk_steps[step]->parallelize_with( pattern );
    parallel_fields.push_back( rk_steps[step]->uri() );
  }

  mysolver.actions().get_child("Synchronize").configure_option("Fields", parallel_fields);

//  std::cout << "solution " << solution->uri().string() << std::endl;
//  std::cout << "residual " << residual->uri().string() << std::endl;
//  std::cout << "wave_speed " << wave_speed->uri().string() << std::endl;

}
Пример #7
0
void YPlus::execute()
{
  Mesh& mesh = this->mesh();

  // Geometry data
  const Field& coords = mesh.geometry_fields().coordinates();
  const Uint nb_nodes = coords.size();
  const Uint dim = coords.row_size();

  // Velocity data
  const Field& velocity_field = common::find_component_recursively_with_tag<Field>(mesh, options().value<std::string>("velocity_tag"));
  const auto velocity_dict_handle = Handle<Dictionary const>(velocity_field.parent());
  cf3_assert(velocity_dict_handle != nullptr);
  const Dictionary& velocity_dict = *velocity_dict_handle;
  const Uint vel_offset = velocity_field.descriptor().offset("Velocity");

  // initialize if needed
  auto volume_node_connectivity = Handle<NodeConnectivity>(mesh.get_child("volume_node_connectivity"));
  if(m_normals.empty())
  {
    // Node-to-element connectivity for the volume elements
    volume_node_connectivity = mesh.create_component<NodeConnectivity>("volume_node_connectivity");
    std::vector< Handle<Entities const> > volume_entities;
    for(const mesh::Elements& elements : common::find_components_recursively_with_filter<mesh::Elements>(mesh, IsElementsVolume()))
    {
      volume_entities.push_back(elements.handle<Entities const>());
    }
    volume_node_connectivity->initialize(nb_nodes, volume_entities);

    mesh.geometry_fields().create_field("wall_velocity_gradient_nodal").add_tag("wall_velocity_gradient_nodal");
    Dictionary& wall_P0 = *mesh.create_component<DiscontinuousDictionary>("wall_P0");

    m_normals.clear();
    for(const Handle<Region>& region : regions())
    {
      for(mesh::Elements& wall_entity : common::find_components_recursively_with_filter<mesh::Elements>(*region, IsElementsSurface()))
      {
        const Uint nb_elems = wall_entity.size();
        const auto& geom_conn = wall_entity.geometry_space().connectivity();
        const ElementType& etype = wall_entity.element_type();
        const Uint element_nb_nodes = etype.nb_nodes();

        m_normals.push_back(std::vector<RealVector>(nb_elems, RealVector(dim)));

        RealMatrix elem_coords(element_nb_nodes, dim);
        for(Uint elem_idx = 0; elem_idx != nb_elems; ++elem_idx)
        {
          const Connectivity::ConstRow conn_row = geom_conn[elem_idx];
          fill(elem_coords, coords, conn_row);
          RealVector normal(dim);
          etype.compute_normal(elem_coords, m_normals.back()[elem_idx]);
          m_normals.back()[elem_idx] /= m_normals.back()[elem_idx].norm();
        }

        wall_entity.create_component<FaceConnectivity>("wall_face_connectivity")->initialize(*volume_node_connectivity);
        wall_entity.create_space("cf3.mesh.LagrangeP0."+wall_entity.element_type().shape_name(),wall_P0);
      }
    }
    wall_P0.build();         // to tell the dictionary that all spaces have been added
    mesh.update_structures(); // to tell the mesh there is a new dictionary added manually
    wall_P0.create_field("wall_velocity_gradient").add_tag("wall_velocity_gradient");
  }

  // Create the y+ field in the geometry dictionary
  if(common::find_component_ptr_with_tag(mesh.geometry_fields(), "yplus") == nullptr)
  {
    mesh.geometry_fields().create_field("yplus").add_tag("yplus");
  }

  // Compute shear stress
  Uint surface_idx = 0;
  Dictionary& wall_P0 = *Handle<mesh::Dictionary>(mesh.get_child_checked("wall_P0"));
  Field& wall_velocity_gradient_field = *Handle<Field>(wall_P0.get_child_checked("wall_velocity_gradient"));
  for(const Handle<Region>& region : regions())
  {
    for(const mesh::Elements& elements : common::find_components_recursively_with_filter<mesh::Elements>(*region, IsElementsSurface()))
    {
      const Uint nb_elements = elements.geometry_space().connectivity().size();
      cf3_assert(elements.element_type().nb_faces() == 1);
      const auto& face_connectivity = *Handle<FaceConnectivity const>(elements.get_child_checked("wall_face_connectivity"));
      const auto& wall_conn = elements.space(wall_P0).connectivity();
      for(Uint surface_elm_idx = 0; surface_elm_idx != nb_elements; ++surface_elm_idx)
      {
        if(face_connectivity.has_adjacent_element(surface_elm_idx, 0))
        {
          const Uint wall_field_idx = wall_conn[surface_elm_idx][0];
          // Get the wall normal vector
          const RealVector& normal = m_normals[surface_idx][surface_elm_idx];
          RealVector3 normal3;
          normal3[0] = normal[0];
          normal3[1] = normal[1];
          normal3[2] = dim == 3 ? normal[2] : 0.;

          // The connected volume element
          NodeConnectivity::ElementReferenceT connected = face_connectivity.adjacent_element(surface_elm_idx, 0);
          const mesh::Entities& volume_entities = *face_connectivity.node_connectivity().entities()[connected.first];
          const Uint volume_elem_idx = connected.second;
          const auto& velocity_conn = volume_entities.space(velocity_dict).connectivity();
          const auto& velocity_sf = volume_entities.space(velocity_dict).shape_function();
          const auto& geom_conn = volume_entities.geometry_space().connectivity();
          const ElementType& volume_etype = volume_entities.element_type();

          const Uint nb_vel_nodes = velocity_sf.nb_nodes();
          const RealVector centroid_mapped_coord = 0.5*(velocity_sf.local_coordinates().colwise().minCoeff() + velocity_sf.local_coordinates().colwise().maxCoeff());
          RealMatrix elem_coords(geom_conn.row_size(), dim);
          fill(elem_coords, coords, geom_conn[volume_elem_idx]);

          RealVector tangential_velocity(nb_vel_nodes); // For every node, the component of the velocity tangential to the wall
          RealVector3 v3;
          for(Uint i = 0; i != nb_vel_nodes; ++i)
          {
            Eigen::Map<RealVector const> v(&velocity_field[velocity_conn[volume_elem_idx][i]][vel_offset], dim);
            v3[0] = v[0];
            v3[1] = v[1];
            v3[2] = dim == 3 ? v[2] : 0.;
            tangential_velocity[i] = v3.cross(normal3).norm();
          }
          wall_velocity_gradient_field[wall_field_idx][0] = fabs((volume_etype.jacobian(centroid_mapped_coord, elem_coords).inverse() * velocity_sf.gradient(centroid_mapped_coord) * tangential_velocity).dot(-normal));
        }
      }
      ++surface_idx;
    }
  }

  wall_velocity_gradient_field.synchronize();

  // Compute a nodal version of the wall velocity gradient
  const auto& wall_node_connectivity = *Handle<NodeConnectivity>(mesh.get_child_checked("wall_node_connectivity"));
  Field& wall_velocity_gradient_field_nodal = *Handle<Field>(mesh.geometry_fields().get_child_checked("wall_velocity_gradient_nodal"));
  for(Uint node_idx = 0; node_idx != nb_nodes; ++node_idx)
  {
    Uint nb_connected_elems = 0;
    wall_velocity_gradient_field_nodal[node_idx][0] = 0;
    for(const NodeConnectivity::ElementReferenceT elref : wall_node_connectivity.node_element_range(node_idx))
    {
      const Uint wall_field_idx = wall_node_connectivity.entities()[elref.first]->space(wall_P0).connectivity()[elref.second][0];
      wall_velocity_gradient_field_nodal[node_idx][0] += wall_velocity_gradient_field[wall_field_idx][0];
      ++nb_connected_elems;
    }
    if(nb_connected_elems != 0)
    {
      wall_velocity_gradient_field_nodal[node_idx][0] /= static_cast<Real>(nb_connected_elems);
    }
  }


  // Set Yplus
  Field& yplus_field = *Handle<Field>(mesh.geometry_fields().get_child_checked("yplus"));
  const Field& wall_distance_field = *Handle<Field>(mesh.geometry_fields().get_child_checked("wall_distance"));
  const auto& node_to_wall_element = *Handle<common::Table<Uint>>(mesh.get_child_checked("node_to_wall_element"));
  const Real nu = physical_model().options().value<Real>("kinematic_viscosity");
  for(Uint node_idx = 0; node_idx != nb_nodes; ++node_idx)
  {
    yplus_field[node_idx][0] = 0;
    if(node_to_wall_element[node_idx][0] != 0)
    {
      const Entities& wall_entities = *wall_node_connectivity.entities()[node_to_wall_element[node_idx][1]];
      const Uint wall_field_idx = wall_entities.space(wall_P0).connectivity()[node_to_wall_element[node_idx][2]][0];
      yplus_field[node_idx][0] = wall_distance_field[node_idx][0] * sqrt(nu*wall_velocity_gradient_field[wall_field_idx][0]) / nu;
    }
    else
    {
      yplus_field[node_idx][0] = wall_distance_field[node_idx][0] * sqrt(nu*wall_velocity_gradient_field_nodal[node_to_wall_element[node_idx][1]][0]) / nu;
    }
  }
}
Пример #8
0
void SetupSingleSolution::execute()
{
  RDM::RDSolver& mysolver = *solver().handle< RDM::RDSolver >();

  if(is_null(m_mesh))
    throw SetupError(FromHere(), "SetupSingleSolution has no configured mesh in [" + uri().string() + "]" );

  Mesh& mesh = *m_mesh;

  Group& fields = mysolver.fields();

  const Uint nbdofs = physical_model().neqs();

  // get the geometry field group

  SpaceFields& geometry = mesh.geometry_fields();

  const std::string solution_space = mysolver.options().option("solution_space").value<std::string>();

  // check that the geometry belongs to the same space as selected by the user

  Handle< SpaceFields > solution_group;

  if( solution_space == geometry.space() )
    solution_group = geometry.handle<SpaceFields>();
  else
  {
    // check if solution space already exists
    solution_group = find_component_ptr_with_name<SpaceFields>( mesh, RDM::Tags::solution() );
    if ( is_null(solution_group) )
    {
      solution_group = mesh.create_space_and_field_group( RDM::Tags::solution(), SpaceFields::Basis::POINT_BASED, "cf3.mesh."+solution_space).handle<SpaceFields>();
    }
    else // not null so check that space is what user wants
    {
      if( solution_space != solution_group->space() )
        throw NotImplemented( FromHere(), "Changing solution space not supported" );
    }
  }

  solution_group->add_tag( solution_space );

  // configure solution

  Handle< Field > solution = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::solution() );
  if ( is_null( solution ) )
  {
    std::string vars;
    for(Uint i = 0; i < nbdofs; ++i)
    {
     vars += "u" + to_str(i) + "[1]";
     if( i != nbdofs-1 ) vars += ",";
    }

    solution = solution_group->create_field( RDM::Tags::solution(), vars ).handle<Field>();

    solution->add_tag(RDM::Tags::solution());
  }

  /// @todo here we should check if space() order is correct,
  ///       if not the change space() by enriching or other appropriate action

  // configure residual

  Handle< Field > residual = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::residual());
  if ( is_null( residual ) )
  {
    residual = solution_group->create_field(Tags::residual(), solution->descriptor().description() ).handle<Field>();
    residual->descriptor().prefix_variable_names("rhs_");
    residual->add_tag(Tags::residual());
  }

  // configure wave_speed

  Handle< Field > wave_speed = find_component_ptr_with_tag<Field>( *solution_group, RDM::Tags::wave_speed());
  if ( is_null( wave_speed ) )
  {
    wave_speed = solution_group->create_field( Tags::wave_speed(), "ws[1]" ).handle<Field>();
    wave_speed->add_tag(Tags::wave_speed());
  }

  // place link to the fields in the Fields group

  if( ! fields.get_child( RDM::Tags::solution() ) )
    fields.create_component<Link>( RDM::Tags::solution()   )->link_to(*solution).add_tag(RDM::Tags::solution());
  if( ! fields.get_child( RDM::Tags::residual() ) )
    fields.create_component<Link>( RDM::Tags::residual()   )->link_to(*residual).add_tag(RDM::Tags::residual());
  if( ! fields.get_child( RDM::Tags::wave_speed() ) )
    fields.create_component<Link>( RDM::Tags::wave_speed() )->link_to(*wave_speed).add_tag(RDM::Tags::wave_speed());


  /// @todo apply here the bubble insertion if needed

  // parallelize the solution if not yet done

  solution->parallelize();

  std::vector<URI> sync_fields;
  sync_fields.push_back( solution->uri() );
  mysolver.actions().get_child("Synchronize")->options().configure_option("Fields", sync_fields);

}