LCOV - code coverage report
Current view: top level - src/mesh - fro_io.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 0 61 0.0 %
Date: 2025-08-19 19:27:09 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : // C++ includes
      21             : #include <fstream>
      22             : #include <iomanip>
      23             : #include <iostream>
      24             : #include <deque>
      25             : #include <map>
      26             : 
      27             : // Local includes
      28             : #include "libmesh/libmesh_config.h"
      29             : #include "libmesh/fro_io.h"
      30             : #include "libmesh/mesh_base.h"
      31             : #include "libmesh/boundary_info.h"
      32             : #include "libmesh/elem.h"
      33             : 
      34             : namespace libMesh
      35             : {
      36             : 
      37             : 
      38             : 
      39             : // ------------------------------------------------------------
      40             : // FroIO  members
      41           0 : void FroIO::write (const std::string & fname)
      42             : {
      43             :   // We may need to gather a DistributedMesh to output it, making that
      44             :   // const qualifier in our constructor a dirty lie
      45           0 :   MeshSerializer serialize(const_cast<MeshBase &>(this->mesh()), !_is_parallel_format);
      46             : 
      47           0 :   if (this->mesh().processor_id() == 0)
      48             :     {
      49             :       // Open the output file stream
      50           0 :       std::ofstream out_stream (fname.c_str());
      51           0 :       libmesh_assert (out_stream.good());
      52             : 
      53             :       // Make sure it opened correctly
      54           0 :       if (!out_stream.good())
      55           0 :         libmesh_file_error(fname.c_str());
      56             : 
      57             :       // Get a reference to the mesh
      58           0 :       const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
      59             : 
      60             :       // Write the header
      61           0 :       out_stream << the_mesh.n_elem()  << " "
      62           0 :                  << the_mesh.n_nodes() << " "
      63           0 :                  << "0 0 "
      64           0 :                  << the_mesh.get_boundary_info().n_boundary_ids()  << " 1\n";
      65             : 
      66             :       // Write the nodes -- 1-based!
      67           0 :       for (auto n : make_range(the_mesh.n_nodes()))
      68           0 :         out_stream << n+1 << " \t"
      69           0 :                    << std::scientific
      70           0 :                    << std::setprecision(this->ascii_precision())
      71           0 :                    << the_mesh.point(n)(0) << " \t"
      72           0 :                    << the_mesh.point(n)(1) << " \t"
      73           0 :                    << 0. << '\n';
      74             : 
      75             :       // Write the elements -- 1-based!
      76           0 :       unsigned int e = 0;
      77           0 :       for (const auto & elem : the_mesh.active_element_ptr_range())
      78             :         {
      79             :           // .fro likes TRI3's
      80           0 :           libmesh_error_msg_if(elem->type() != TRI3,
      81             :                                "ERROR:  .fro format only valid for triangles!\n"
      82             :                                << "  writing of " << fname << " aborted.");
      83             : 
      84           0 :           out_stream << ++e << " \t";
      85             : 
      86           0 :           for (const Node & node : elem->node_ref_range())
      87           0 :             out_stream << node.id()+1 << " \t";
      88             : 
      89             :           //   // LHS -> RHS Mapping, for inverted triangles
      90             :           //   out_stream << elem->node_id(0)+1 << " \t";
      91             :           //   out_stream << elem->node_id(2)+1 << " \t";
      92             :           //   out_stream << elem->node_id(1)+1 << " \t";
      93             : 
      94           0 :           out_stream << "1\n";
      95           0 :         }
      96             : 
      97             :       // Write BCs.
      98             :       {
      99             :         const std::set<boundary_id_type> & bc_ids =
     100           0 :           the_mesh.get_boundary_info().get_boundary_ids();
     101             : 
     102             :         // Build a list of (elem, side, bc) tuples.
     103           0 :         auto bc_triples = the_mesh.get_boundary_info().build_side_list();
     104             : 
     105             :         // Map the boundary ids into [1,n_bc_ids],
     106             :         // treat them one at a time.
     107           0 :         boundary_id_type bc_id=0;
     108           0 :         for (const auto & id : bc_ids)
     109             :           {
     110           0 :             std::deque<dof_id_type> node_list;
     111             : 
     112             :             std::map<dof_id_type, dof_id_type>
     113           0 :               forward_edges, backward_edges;
     114             : 
     115             :             // Get all sides on this element with the relevant BC id.
     116           0 :             for (const auto & t : bc_triples)
     117           0 :               if (std::get<2>(t) == id)
     118             :                 {
     119             :                   // need to build up node_list as a sorted array of edge nodes...
     120             :                   // for the following:
     121             :                   // a---b---c---d---e
     122             :                   // node_list [ a b c d e];
     123             :                   //
     124             :                   // the issue is just how to get this out of the elem/side based data structure.
     125             :                   // the approach is to build up 'chain links' like this:
     126             :                   // a---b b---c c---d d---e
     127             :                   // and piece them together.
     128             :                   //
     129             :                   // so, for an arbitrary edge n0---n1, we build the
     130             :                   // "forward_edges"  map n0-->n1
     131             :                   // "backward_edges" map n1-->n0
     132             :                   // and then start with one chain link, and add on...
     133             :                   //
     134             :                   std::unique_ptr<const Elem> side =
     135           0 :                     the_mesh.elem_ref(std::get<0>(t)).build_side_ptr(std::get<1>(t));
     136             : 
     137             :                   const dof_id_type
     138           0 :                     n0 = side->node_id(0),
     139           0 :                     n1 = side->node_id(1);
     140             : 
     141             :                   // insert into forward-edge set
     142           0 :                   forward_edges.emplace(n0, n1);
     143             : 
     144             :                   // insert into backward-edge set
     145           0 :                   backward_edges.emplace(n1, n0);
     146             : 
     147             :                   // go ahead and add one edge to the list -- this will give us the beginning of a
     148             :                   // chain to work from!
     149           0 :                   if (node_list.empty())
     150             :                     {
     151           0 :                       node_list.push_front(n0);
     152           0 :                       node_list.push_back (n1);
     153             :                     }
     154           0 :                 }
     155             : 
     156             :             // we now have the node_list with one edge, the forward_edges, and the backward_edges
     157             :             // the node_list will be filled when (node_list.size() == (n_edges+1))
     158             :             // until that is the case simply add on to the beginning and end of the node_list,
     159             :             // building up a chain of ordered nodes...
     160           0 :             const std::size_t n_edges = forward_edges.size();
     161             : 
     162           0 :             while (node_list.size() != (n_edges+1))
     163             :               {
     164             :                 const dof_id_type
     165           0 :                   front_node = node_list.front(),
     166           0 :                   back_node  = node_list.back();
     167             : 
     168             :                 // look for front_pair in the backward_edges list
     169           0 :                 if (const auto pos = backward_edges.find(front_node);
     170           0 :                     pos != backward_edges.end())
     171             :                   {
     172           0 :                     node_list.push_front(pos->second);
     173           0 :                     backward_edges.erase(pos);
     174             :                   }
     175             : 
     176             :                 // look for back_pair in the forward_edges list
     177           0 :                 if (const auto pos = forward_edges.find(back_node);
     178           0 :                     pos != forward_edges.end())
     179             :                   {
     180           0 :                     node_list.push_back(pos->second);
     181           0 :                     forward_edges.erase(pos);
     182             :                   }
     183             :               }
     184             : 
     185           0 :             out_stream << ++bc_id << " " << node_list.size() << '\n';
     186             : 
     187           0 :             for (const auto & node_id : node_list)
     188           0 :               out_stream << node_id + 1 << " \t0\n";
     189             :           }
     190             :       }
     191           0 :     }
     192           0 : }
     193             : 
     194             : } // namespace libMesh

Generated by: LCOV version 1.14