예제 #1
0
  void OverlappingFluidSolidMap::build_maps( MultiphysicsSystem & system,
                                             const libMesh::PointLocatorBase & point_locator,
                                             const std::set<libMesh::subdomain_id_type> & solid_ids,
                                             const std::set<libMesh::subdomain_id_type> & fluid_ids,
                                             const DisplacementVariable & solid_disp_vars )
  {
    const libMesh::MeshBase & mesh = system.get_mesh();

    libMesh::UniquePtr<libMesh::DiffContext> raw_context = system.build_context();
    libMesh::UniquePtr<libMesh::FEMContext> fem_context( libMesh::cast_ptr<libMesh::FEMContext *>(raw_context.release()) );

    if( !mesh.is_serial() )
      libmesh_error_msg("ERROR: build_maps currently only implemented for ReplicatedMesh!");

    for( std::set<libMesh::subdomain_id_type>::const_iterator solid_id_it = solid_ids.begin();
         solid_id_it != solid_ids.end(); ++solid_id_it )
      for( libMesh::MeshBase::const_element_iterator e = mesh.active_subdomain_elements_begin(*solid_id_it);
           e != mesh.active_local_subdomain_elements_end(*solid_id_it);
           ++e )
        {
          // Convenience
          const libMesh::Elem * solid_elem = *e;

          // Setup FEMContext for computing solid displacements
          const std::vector<libMesh::Point>& qpoints =
            fem_context->get_element_fe(solid_disp_vars.u(),2)->get_xyz();

          fem_context->get_element_fe(solid_disp_vars.u(),2)->get_phi();

          fem_context->pre_fe_reinit(system,solid_elem);
          fem_context->elem_fe_reinit();

          // Find what fluid element contains each of the quadrature points and cache
          for( unsigned int qp = 0; qp < qpoints.size(); qp++ )
            {
              libMesh::Real u_disp = 0;
              libMesh::Real v_disp = 0;
              libMesh::Real w_disp = 0;

              fem_context->interior_value(solid_disp_vars.u(), qp, u_disp);
              if( solid_disp_vars.dim() >= 2 )
                fem_context->interior_value(solid_disp_vars.v(), qp, v_disp);
              if( solid_disp_vars.dim() == 3 )
                fem_context->interior_value(solid_disp_vars.w(), qp, w_disp);

              libMesh::Point U( u_disp, v_disp, w_disp );

              // We need to look for overlap with *displaced* solid point
              libMesh::Point x = qpoints[qp]+U;

              const libMesh::Elem * fluid_elem = point_locator( x, &fluid_ids );

              if( !fluid_elem )
                libmesh_error_msg("ERROR: Could not find fluid element for given displacement! Likely solid displaced off the fluid mesh!");

              // Now add to the solid elem->overlapping fluid elems map, but only if
              // the solid elem belongs to this processor
              {
                std::map<libMesh::dof_id_type,std::vector<unsigned int> > & fluid_elem_map =
                  _solid_to_fluid_map[solid_elem->id()];

                // The solid quadrature point that are in this overlapping fluid/solid element pair
                std::vector<unsigned int>& solid_qps = fluid_elem_map[fluid_elem->id()];
                solid_qps.push_back(qp);
              }

              // Now add to the fluid elem->overlapping solid elems map, but only if
              // the fluid elem belongs to this processor
              {
                std::map<libMesh::dof_id_type,std::vector<unsigned int> > & solid_elem_map =
                  _fluid_to_solid_map[fluid_elem->id()];

                // The solid quadrature point that are in this overlapping fluid/solid element pair
                std::vector<unsigned int>& solid_qps = solid_elem_map[solid_elem->id()];
                solid_qps.push_back(qp);
              }
            }
        }
  }