Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Main/MeshConvDriver.cpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.
7 : : All rights reserved. See the LICENSE file for details.
8 : : \brief Mesh converter driver
9 : : \details Mesh converter driver.
10 : : */
11 : : // *****************************************************************************
12 : :
13 : : #include "Types.hpp"
14 : : #include "Tags.hpp"
15 : : #include "MeshConvDriver.hpp"
16 : : #include "MeshFactory.hpp"
17 : : #include "TaggedTupleDeepPrint.hpp"
18 : : #include "Writer.hpp"
19 : :
20 : : #include "NoWarning/meshconv.decl.h"
21 : :
22 : : using meshconv::MeshConvDriver;
23 : :
24 : : extern CProxy_Main mainProxy;
25 : :
26 : 18 : MeshConvDriver::MeshConvDriver( const ctr::CmdLine& cmdline, int ) :
27 : 36 : m_print( cmdline.logname( cmdline.get< tag::io, tag::screen >(),
28 : 18 : cmdline.get< tag::io, tag::nrestart >() ),
29 : 36 : cmdline.get< tag::verbose >() ? std::cout : std::clog,
30 : : std::ios_base::app ),
31 : 18 : m_reorder( cmdline.get< tag::reorder >() ),
32 : : m_input(),
33 [ + - ][ + - ]: 54 : m_output()
34 : : // *****************************************************************************
35 : : // Constructor
36 : : //! \param[in] cmdline Command line object storing data parsed from the command
37 : : //! line arguments
38 : : // *****************************************************************************
39 : : {
40 : : // Save input file name
41 [ + - ]: 18 : m_input = cmdline.get< tag::io, tag::input >();
42 : : // Save output file name
43 [ + - ]: 18 : m_output = cmdline.get< tag::io, tag::output >();
44 : :
45 : : // Output command line object to file
46 [ + - ][ + - ]: 36 : auto logfilename = tk::meshconv_executable() + "_input.log";
47 [ + - ]: 18 : tk::Writer log( logfilename );
48 [ + - ][ + - ]: 18 : tk::print( log.stream(), "cmdline", cmdline );
49 : 18 : }
50 : :
51 : : void
52 : 18 : MeshConvDriver::execute() const
53 : : // *****************************************************************************
54 : : // Execute: Convert mesh file
55 : : // *****************************************************************************
56 : : {
57 [ + - ]: 18 : m_print.endsubsection();
58 : :
59 : 36 : std::vector< std::pair< std::string, tk::real > > times;
60 : :
61 : : // If input filename contains a '%', we aggregate multiple files
62 [ + + ]: 18 : if (m_input.find('%') == std::string::npos) {
63 : :
64 : : // Convert single mesh
65 : :
66 [ + - ]: 17 : times.push_back( {} );
67 [ + - ]: 34 : auto mesh = tk::readUnsMesh( m_print, m_input, times[0] );
68 [ + - ]: 17 : auto wtimes = tk::writeUnsMesh( m_print, m_output, mesh, m_reorder );
69 [ + - ]: 17 : times.insert( end(times), begin(wtimes), end(wtimes) );
70 : :
71 : : } else {
72 : :
73 : : // Aggregate multiple meshes containing surface output
74 : :
75 : : // Find a '%' sign in the input filename, and assuming a syntax of
76 : : // '.<nfile>.%', find '<nfile>' as the number of files to aggregate.
77 : 1 : auto percent_pos = m_input.find( '%' );
78 [ + - ]: 2 : auto input_basename = m_input.substr( 0, percent_pos );
79 : 1 : auto dot1 = m_input.find_last_of( '.', percent_pos );
80 : 1 : auto dot2 = m_input.find_last_of( '.', dot1-1 );
81 [ + - ]: 2 : auto nfile_str = m_input.substr( dot2+1, dot1-dot2-1 );
82 [ + - ]: 2 : std::stringstream ss( nfile_str );
83 [ - + ]: 1 : if (nfile_str.empty())
84 [ - - ][ - - ]: 0 : Throw( "The percent sign must be followed by an "
[ - - ]
85 : : "integer, the number of files to aggregate" );
86 : : std::size_t nfile;
87 [ + - ]: 1 : ss >> nfile;
88 [ + - ][ + - ]: 3 : m_print.diag( "Aggregating " + std::to_string(nfile) +
[ + - ][ + - ]
89 [ + - ][ + - ]: 2 : " files from base filename: '" + input_basename +'\'' );
90 : :
91 : 1 : const auto eps = std::numeric_limits< tk::real >::epsilon();
92 : :
93 : : // Lambda to echo some diagnostics on the mesh being processes to screen
94 : 10 : auto diag = [&]( const std::string& name, const tk::UnsMesh& mesh ){
95 [ + - ][ + - ]: 30 : m_print.diag( name + ": ntri: " +
[ + - ]
96 [ + - ][ + - ]: 40 : std::to_string(mesh.triinpoel().size()/3) +
97 [ + - ][ + - ]: 40 : ", ntime: " + std::to_string(mesh.vartimes().size()) +
[ + - ]
98 [ + - ][ + - ]: 30 : (!mesh.nodevars().empty() ? ", nvar: " +
[ - - ][ - + ]
[ - - ]
99 [ + - ][ + - ]: 40 : std::to_string(mesh.nodevars()[0].size()) : "") +
[ + - ][ - - ]
100 [ + - ][ + - ]: 30 : (!mesh.nodevars()[0].empty() ? ", npoin: " +
[ - - ][ - + ]
[ - - ]
101 [ + - ][ + - ]: 20 : std::to_string(mesh.nodevars()[0][0].size()) : "") );
[ - - ]
102 : 10 : };
103 : :
104 : : // Output-mesh containers, will store aggregated surface(s) and field output
105 : 2 : tk::UnsMesh::Coords coords;
106 : 1 : auto& X = coords[0];
107 : 1 : auto& Y = coords[1];
108 : 1 : auto& Z = coords[2];
109 : 1 : std::size_t npoin = 0;
110 : 2 : std::vector< std::size_t > otriinpoel;
111 : 2 : std::vector< std::string > nodevarnames;
112 : 2 : std::vector< tk::real > vartimes;
113 : 2 : std::vector< std::vector< std::vector< tk::real > > > nodevars;
114 : : // Counter for number of non-empty meshes processed
115 : 1 : std::size_t k = 0;
116 [ + + ]: 31 : for (std::size_t m=0; m<nfile; ++m) {
117 [ + - ][ + - ]: 30 : std::string name = input_basename + std::to_string(m);
118 [ + - ]: 30 : times.push_back( {} );
119 [ + - ]: 30 : auto mesh = tk::readUnsMesh( m_print, name, times.back() );
120 : 30 : const auto& triinpoel = mesh.triinpoel();
121 : : // Skip meshes with a single triange cell
122 [ + + ]: 30 : if (triinpoel.size() == 3) continue;
123 : 9 : const auto& x = mesh.x();
124 : 9 : const auto& y = mesh.y();
125 : 9 : const auto& z = mesh.z();
126 [ + - ]: 9 : nodevarnames = mesh.nodevarnames();
127 [ + - ]: 9 : vartimes = mesh.vartimes();
128 : : // Echo some diagnostics on the mesh being processes to screen
129 [ + - ]: 9 : diag( name, mesh );
130 : : // Aggregate data from each triangle element in mesh
131 [ + + ]: 63693 : for (std::size_t e=0; e<triinpoel.size()/3; ++e) {
132 [ + + ]: 254736 : for (std::size_t n=0; n<3; ++n) {
133 : 191052 : auto j = triinpoel[ e*3+n ];
134 : 191052 : bool visited = false;
135 : : // WARNING: linear search below, will not scale well
136 [ + + ]: 3378984362 : for (std::size_t i=0; i<X.size(); ++i) {
137 : : // If mesh point has already been seen (on a previous mesh)
138 [ + + ]: 3939506020 : if (std::abs(x[j]-X[i]) < eps &&
139 [ + + ][ + + ]: 3939506020 : std::abs(y[j]-Y[i]) < eps &&
[ + + ]
140 : 10327686 : std::abs(z[j]-Z[i]) < eps)
141 : : { // no point in connectivity but nothing else
142 : 159179 : visited = true;
143 [ + - ]: 159179 : otriinpoel.push_back( i );
144 : : }
145 : : }
146 [ + + ]: 191052 : if (!visited) { // Mesh point not yet seen
147 : : // save coordinates and (global) point id in aggregated connectivity
148 [ + - ]: 31873 : X.push_back( x[j] );
149 [ + - ]: 31873 : Y.push_back( y[j] );
150 [ + - ]: 31873 : Z.push_back( z[j] );
151 [ + - ]: 31873 : otriinpoel.push_back( npoin );
152 : : // aggregate nodal field data for all times and variables
153 : 31873 : std::size_t time = 0;
154 : 31873 : std::size_t varid = 0;
155 [ + + ]: 127492 : for (const auto& t : mesh.nodevars()) { // for all times
156 [ + + ][ + + ]: 95619 : if (k == 0 && npoin == 0) nodevars.push_back( {} );
[ + - ]
157 [ + + ]: 669333 : for (const auto& v : t) { // for all variables
158 [ + + ][ + + ]: 573714 : if (k == 0 && npoin == 0) nodevars.back().push_back( {} );
[ + - ]
159 [ + - ]: 573714 : nodevars[time][varid].push_back( v[j] );
160 : 573714 : ++varid;
161 : : }
162 : 95619 : ++time;
163 : 95619 : varid = 0;
164 : : }
165 : 31873 : ++npoin; // increase number of nodes in output mesh
166 : : }
167 : : }
168 : : }
169 : 9 : ++k; // increase number of non-empty meshes processed
170 : : }
171 : :
172 : : // Construct aggregated output mesh
173 [ + - ]: 2 : tk::UnsMesh outmesh( coords, otriinpoel, nodevarnames, vartimes, nodevars );
174 : : // Echo diagnostics on the aggreegate output mesh
175 [ + - ]: 1 : diag( m_output, outmesh );
176 : : // Write output mesh to file
177 [ + - ]: 1 : auto wtimes = tk::writeUnsMesh( m_print, m_output, outmesh, m_reorder );
178 : : // Collect wall-clock time data
179 [ + - ]: 1 : times.insert( end(times), begin(wtimes), end(wtimes) );
180 : :
181 : : }
182 : :
183 [ + - ]: 18 : mainProxy.timestamp( times );
184 : :
185 [ + - ]: 18 : mainProxy.finalize();
186 : 18 : }
|