Salome HOME
bd388f6b8ac39c3aaef4e47dcc7dfcaf2f24ebb7
[modules/homard.git] / src / FrontTrack / FrontTrack.cxx
1 // Copyright (C) 2017-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File      : FrontTrack.cxx
20 // Created   : Tue Apr 25 17:20:28 2017
21 // Author    : Edward AGAPOV (eap)
22
23 #include "FrontTrack.hxx"
24 #include "FrontTrack_NodeGroups.hxx"
25 #include "FrontTrack_Utils.hxx"
26
27 #include <MCAuto.hxx>
28 #include <MEDCouplingMemArray.hxx>
29 #include <MEDFileMesh.hxx>
30
31 #include <XAO_Xao.hxx>
32 #include <XAO_BrepGeometry.hxx>
33
34 #include <stdexcept>
35
36 #include <OSD_Parallel.hxx>
37
38 /*!
39  * \brief Relocate nodes to lie on geometry
40  *  \param [in] theInputMedFile - a MED file holding a mesh including nodes that will be
41  *         moved onto the geometry
42  *  \param [in] theOutputMedFile - a MED file to create, that will hold a modified mesh
43  *  \param [in] theInputNodeFiles - an array of names of files describing groups of nodes that
44  *         will be moved onto the geometry
45  *  \param [in] theXaoFileName - a path to a file in XAO format holding the geometry and
46  *         the geometrical groups.
47  *  \param [in] theIsParallel - if \c true, all processors are used to treat boundary shapes
48  *          in parallel.
49  */
50 void FrontTrack::track( const std::string&                 theInputMedFile,
51                         const std::string&                 theOutputMedFile,
52                         const std::vector< std::string > & theInputNodeFiles,
53                         const std::string&                 theXaoFileName,
54                         bool                               theIsParallel )
55 {
56   // check arguments
57 #ifdef _DEBUG_
58   std::cout << "FrontTrack::track" << std::endl;
59 #endif
60
61   if ( theInputNodeFiles.empty() )
62     return;
63
64 #ifdef _DEBUG_
65   std::cout << "Input MED file: " << theInputMedFile << std::endl;
66 #endif
67   if ( !FT_Utils::fileExists( theInputMedFile ))
68     throw std::invalid_argument( "Input MED file does not exist: " + theInputMedFile );
69
70 #ifdef _DEBUG_
71   std::cout << "Output MED file: " << theOutputMedFile << std::endl;
72 #endif
73   if ( !FT_Utils::canWrite( theOutputMedFile ))
74     throw std::invalid_argument( "Can't create the output MED file: " + theOutputMedFile );
75
76   std::vector< std::string > theNodeFiles ;
77   for ( size_t i = 0; i < theInputNodeFiles.size(); ++i )
78   {
79 #ifdef _DEBUG_
80     std::cout << "Initial input node file #"<<i<<": " << theInputNodeFiles[i] << std::endl;
81 #endif
82     if ( !FT_Utils::fileExists( theInputNodeFiles[i] ))
83       throw std::invalid_argument( "Input node file does not exist: " + theInputNodeFiles[i] );
84     // the name of the groupe on line #1, then the numbers of nodes on line #>1
85     // keep only files with more than 1 line:
86     std::ifstream fichier(theInputNodeFiles[i].c_str());
87     std::string s;
88     unsigned int nb_lines = 0;
89     while(std::getline(fichier,s)) ++nb_lines;
90 //     std::cout << ". nb_lines: " << nb_lines << std::endl;
91     if ( nb_lines >= 2 ) { theNodeFiles.push_back( theInputNodeFiles[i] ); }
92   }
93 #ifdef _DEBUG_
94   for ( size_t i = 0; i < theNodeFiles.size(); ++i )
95   { std::cout << "Valid input node file #"<<i<<": " << theNodeFiles[i] << std::endl; }
96 #endif
97
98 #ifdef _DEBUG_
99   std::cout << "XAO file: " << theXaoFileName << std::endl;
100 #endif
101   if ( !FT_Utils::fileExists( theXaoFileName ))
102     throw std::invalid_argument( "Input XAO file does not exist: " + theXaoFileName );
103
104   // read a mesh
105
106 #ifdef _DEBUG_
107   std::cout << "Lecture du maillage" << std::endl;
108 #endif
109   MEDCoupling::MCAuto< MEDCoupling::MEDFileUMesh >
110     mfMesh( MEDCoupling::MEDFileUMesh::New( theInputMedFile ));
111   if ( mfMesh.isNull() )
112     throw std::invalid_argument( "Failed to read the input MED file: " + theInputMedFile );
113
114   MEDCoupling::DataArrayDouble * nodeCoords = mfMesh->getCoords();
115   if ( !nodeCoords || nodeCoords->empty() )
116     throw std::invalid_argument( "No nodes in the input mesh" );
117
118
119   // read a geometry
120
121 #ifdef _DEBUG_
122   std::cout << "Lecture de la geometrie" << std::endl;
123 #endif
124   XAO::Xao xao;
125   if ( !xao.importXAO( theXaoFileName ) || !xao.getGeometry() )
126     throw std::invalid_argument( "Failed to read the XAO input file: " + theXaoFileName );
127
128 #ifdef _DEBUG_
129   std::cout << "Conversion en BREP" << std::endl;
130 #endif
131   XAO::BrepGeometry* xaoGeom = dynamic_cast<XAO::BrepGeometry*>( xao.getGeometry() );
132   if ( !xaoGeom || xaoGeom->getTopoDS_Shape().IsNull() )
133     throw std::invalid_argument( "Failed to get a BREP shape from the XAO input file" );
134
135
136   // read groups of nodes and associate them with boundary shapes using names (no projection so far)
137
138 #ifdef _DEBUG_
139   std::cout << "Lecture des groupes" << std::endl;
140 #endif
141   FT_NodeGroups nodeGroups;
142   nodeGroups.read( theNodeFiles, &xao, nodeCoords );
143 #ifdef _DEBUG_
144   std::cout << "Nombre de groupes : " << nodeGroups.nbOfGroups() << std::endl;
145 #endif
146
147   // project nodes to the boundary shapes and change their coordinates
148
149 #ifdef _DEBUG_
150   std::cout << "Projection des noeuds, theIsParallel=" << theIsParallel << std::endl;
151 #endif
152   OSD_Parallel::For( 0, nodeGroups.nbOfGroups(), nodeGroups, !theIsParallel );
153
154   // save the modified mesh
155
156 #ifdef _DEBUG_
157   std::cout << "Ecriture du maillage" << std::endl;
158 #endif
159   const int erase = 2;
160   mfMesh->write( theOutputMedFile, /*mode=*/erase );
161
162   if ( !nodeGroups.isOK() )
163     throw std::runtime_error("Unable to project some nodes");
164 }