TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
EcrFicPartage.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <EcrFicPartage.h>
17#include <PE_Groups.h>
18#include <Comm_Group.h>
19#include <communications.h>
20#include <Perf_counters.h>
21
22Implemente_instanciable_sans_constructeur_ni_destructeur(EcrFicPartage,"EcrFicPartage",SFichier);
24Sortie& EcrFicPartage::printOn(Sortie& s) const { throw; }
25
27{
28 obuffer_ptr_ = new OBuffer;
29 set_bin(false);
30}
31
32/*! @brief Opens the file with the given mode and prot parameters. These parameters are the parameters of the standard open method
33 *
34 */
35EcrFicPartage::EcrFicPartage(const char* name,IOS_OPEN_MODE mode)
36{
37 obuffer_ptr_ = new OBuffer;
38 set_bin(false);
39 obuffer_ptr_->set_64b(this->is_64b());
40
41 ouvrir(name, mode);
42}
43
44inline OBuffer& EcrFicPartage::get_obuffer()
45{
46 assert(obuffer_ptr_);
47 return *obuffer_ptr_;
48}
49
50/*! @brief Opens the file with the given mode and prot parameters. These parameters are the parameters of the standard open method
51 *
52 */
53int EcrFicPartage::ouvrir(const char* name,IOS_OPEN_MODE mode)
54{
55 // Sanity check: are all processors present?
56 barrier();
57
58 int ok = 1;
59 if(je_suis_maitre())
60 {
61#ifdef FILESYSTEM_NON_GLOBAL
62 nom_fic_ = pwd();
63 nom_fic_ += "/";
64 nom_fic_ += name;
65#else
66 nom_fic_ = name;
67#endif
68 // Only the master opens the file
69 ok = SFichier::ouvrir((const char *)nom_fic_, mode);
70 }
71 syncfile();
72
73 // Modif B.Math. 22/09/2004: all processors go through the buffer,
74 // including the master.
75 get_obuffer().new_buffer();
76 return ok;
77}
78
79
80/*! @brief Closes the file
81 *
82 */
84{
85 close();
86 delete obuffer_ptr_;
87 obuffer_ptr_ = 0;
88}
89
91{
92 // Sanity check: is everyone present?
93 barrier();
94 const int buflen = get_obuffer().len();
95 if(buflen > 0)
96 {
97 Cerr << "***** WARNING : EcrFicPartage::close() ******* "<<nom_fic_
98 << "\non PE " << me() << " the buffer is not empty\n"
99 << " (Missing syncfile) : one makes a last syncfile" << finl;
100 Cerr<<get_obuffer().str()<<finl;
101 }
102#ifndef NDEBUG
103 // Is there a processor on which data still remains
104 const trustIdType maxbuflen = mp_sum(buflen);
105 if (maxbuflen > 0)
106 syncfile();
107#endif
108 if(je_suis_maitre())
110#ifndef NDEBUG
111 if (maxbuflen > 0)
112 {
113 Cerr<<"It missed a syncfile somewhere"<<finl;
114 Cerr<<"Indeed, maxbuflen =" << maxbuflen << finl;
115 Cerr<<"GF prefers to stop the calculation to correct "<<finl;
116 exit();
117 }
118#endif
119}
120/*! @brief Allows the calling process to block waiting for the common resource shared by all processes, which is the shared file.
121 *
122 * If the calling process is not the first, it waits for the previous process to indicate the position in the file where it should write next.
123 * This method is systematically called before any new write to the file.
124 *
125 * @return (Sortie&) *this
126 */
128{
129 return *this;
130}
131
132
133/*! @brief Releases the critical resource for the next process.
134 *
135 * The calling process, unless it is the first process of the group, sends
136 * its current position to the next process in the group. This method should
137 * be called after each write to the file.
138 *
139 * @return (Sortie&) *this
140 */
142{
143 return *this;
144}
145
146/*! @brief Triggers writing to disk of the data accumulated on the different processors since the last call to syncfile().
147 *
148 * Data is written in ascending processor order.
149 * This function must be called the same number of times on all processors!
150 *
151 * Example:
152 * processor 0: processor 1:
153 * file << "pe0 : 1" << finl; file << "pe1 : 1" << finl;
154 * file << "pe0 : 2" << finl; file << "pe1 : 2" << finl;
155 * file.syncfile(); file.syncfile();
156 * file << "pe0 : 3" << finl; file << "pe1 : 3" << finl;
157 * file << "pe0 : 4" << finl;
158 * file.syncfile(); file.syncfile();
159 * file << "pe0 : end" << finl; // processor 1 writes no data
160 * file.syncfile(); file.syncfile();
161 *
162 * File contents:
163 * pe0 : 1
164 * pe0 : 2
165 * pe1 : 1
166 * pe1 : 2
167 * pe0 : 3
168 * pe0 : 4
169 * pe1 : 3
170 * pe0 : end
171 *
172 */
174{
175 // In ASCII mode, data is converted to ASCII when written to the buffer.
176 // A second conversion occurs when writing to disk
177 // (depending on the operating system, '\n' may be encoded differently for example).
178 // So, in ASCII mode, we use:
179 // file << buffer;
180 // and in binary mode:
181 // file.write(buffer, size);
182 // Because file << buffer determines the buffer length by looking for the '\0' character,
183 // in ASCII mode the buffer must end with a '\0' character,
184 // which is added here:
185
186 if (! bin_)
187 {
188 get_obuffer().put_null_char();
189 }
190
191 const Comm_Group& group = PE_Groups::current_group();
192 if(je_suis_maitre())
193 {
194 int p;
195 const int nb_proc = nproc();
196 for(p=0; p<nb_proc; p++)
197 {
198 const char * buffer_data = 0;
199 char * allocated_buffer = 0;
200 int buf_size;
201
202 // We retrieve data from processor p, either directly (p==me()),
203 // or via communication:
204 if (p == me())
205 {
206 // Writing my own data: I take it from the buffer.
207 // This pointer may be null:
208 buffer_data = get_obuffer().str();
209 buf_size = get_obuffer().len();
210 }
211 else
212 {
213 // Writing data from another processor; retrieve it.
214 int dummy = 0;
215 envoyer(dummy, p, 100); // Signal processor p so it sends its data
216 recevoir(buf_size, p, 100);
217 if (buf_size > 0)
218 {
219 buffer_data = allocated_buffer = new char[buf_size];
220 group.recv(p, allocated_buffer, buf_size, 100);
221 }
222 }
223 // Write to disk file
224 if (buf_size > 0)
225 {
226 assert(buffer_data);
227 ostream& os = get_ostream();
228 if (bin_)
229 {
230 // Binary write without conversion:
231 statistics().begin_count(STD_COUNTERS::IO_EcrireFicPartageBin,statistics().get_last_opened_counter_level()+1);
232 os.write(buffer_data, buf_size);
233 statistics().end_count(STD_COUNTERS::IO_EcrireFicPartageBin,1,buf_size);
234 }
235 else
236 {
237 // Verify that the buffer indeed ends with a 0 character:
238 assert(buffer_data[buf_size-1] == 0);
239 // Write buffer_data as a string
240 // (conversion of \n on certain systems, etc...)
241 os << buffer_data;
242 }
243 }
244 if (allocated_buffer)
245 delete[] allocated_buffer;
246 }
247 // Force everything to be written to disk immediately:
248 // (call to the low-level flush function, not trio's).
249 get_ostream().flush();
250 }
251 else
252 {
253 // Send the buffer to the master processor:
254 // We wait for it to request the data to avoid congesting the network:
255 // (otherwise all processors send their data simultaneously)
256 int dummy;
257 recevoir(dummy, 0, 100);
258 int buf_size = get_obuffer().len();
259 envoyer(buf_size, 0, 100);
260 // If the size is non-zero, send the buffer:
261 if (buf_size > 0)
262 {
263 const char * buffer_data = get_obuffer().str();
264 group.send(0, buffer_data, buf_size, 100);
265 }
266 }
267
268 // Empty the buffer:
269 get_obuffer().new_buffer();
270 return *this;
271}
272
273void EcrFicPartage::precision(int i) { get_obuffer().precision(i); }
274
275int EcrFicPartage::get_precision() { return get_obuffer().get_precision(); }
276
278{
279 get_obuffer() << ob;
280 return *this;
281}
282
283Sortie& EcrFicPartage::operator <<(const std::string& str) { return operator_template<std::string>(str);}
284Sortie& EcrFicPartage::operator <<(const Separateur& s) { return operator_template<Separateur>(s);}
285Sortie& EcrFicPartage::operator <<(const Objet_U& ob) { return operator_template<Objet_U>(ob);}
286Sortie& EcrFicPartage::operator <<(const int ob) { return operator_template<int>(ob);}
287Sortie& EcrFicPartage::operator <<(const unsigned ob) { return operator_template<unsigned>(ob);}
288Sortie& EcrFicPartage::operator <<(const float ob) { return operator_template<float>(ob);}
289Sortie& EcrFicPartage::operator <<(const double ob) { return operator_template<double>(ob);}
290Sortie& EcrFicPartage::operator <<(const long ob) { return operator_template<long>(ob);}
291Sortie& EcrFicPartage::operator <<(const long long ob) { return operator_template<long long>(ob);}
292Sortie& EcrFicPartage::operator <<(const unsigned long ob) { return operator_template<unsigned long>(ob);}
293
294
295int EcrFicPartage::put(const unsigned* ob, std::streamsize n, std::streamsize pas) { return put_template<unsigned>(ob,n,pas); }
296int EcrFicPartage::put(const int* ob, std::streamsize n, std::streamsize pas) { return put_template<int>(ob,n,pas); }
297int EcrFicPartage::put(const long* ob, std::streamsize n, std::streamsize pas) { return put_template<long>(ob,n,pas); }
298int EcrFicPartage::put(const long long* ob, std::streamsize n, std::streamsize pas) { return put_template<long long>(ob,n,pas); }
299int EcrFicPartage::put(const float* ob, std::streamsize n, std::streamsize pas) { return put_template<float>(ob,n,pas); }
300int EcrFicPartage::put(const double* ob, std::streamsize n, std::streamsize pas) { return put_template<double>(ob,n,pas); }
301
302
304{
306 get_obuffer().set_bin(bin_);
307}
308
310{
311 SFichier::set_64b(is64);
312 get_obuffer().set_64b(is64);
313}
314
315Sortie& EcrFicPartage::flush() { return (*this); }
virtual void set_bin(bool bin)
Definition AbstractIO.h:39
bool bin_
Is this a binary flux?
Definition AbstractIO.h:50
bool is_64b() const
Definition AbstractIO.h:37
virtual void set_64b(bool is_64b)
Definition AbstractIO.h:38
: This class describes a group of processors on which
Definition Comm_Group.h:37
virtual void send(int pe, const void *buffer, int size, int tag) const =0
virtual void recv(int pe, void *buffer, int size, int tag) const =0
int put(const unsigned *ob, std::streamsize n, std::streamsize pas) override
int get_precision() override
~EcrFicPartage() override
Closes the file.
Sortie & unlockfile() override
Releases the critical resource for the next process.
Sortie & lockfile() override
Allows the calling process to block waiting for the common resource shared by all processes,...
Sortie & flush() override
void set_bin(bool bin) override
Sortie & operator<<(const char *ob) override
Writes a character string.
int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out) override
Opens the file with the given mode and prot parameters. These parameters are the parameters of the st...
Sortie & syncfile() override
Triggers writing to disk of the data accumulated on the different processors since the last call to s...
void precision(int) override
void set_64b(bool is64) override
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
friend class Sortie
Definition Objet_U.h:70
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
Objet_U()
Default constructor: assigns a unique identifier to the object (object_id_) and registers the object ...
Definition Objet_U.cpp:54
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
static const Comm_Group & current_group()
Returns a reference to the current active processor group.
Definition PE_Groups.h:64
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
static double mp_sum(double)
Computes the sum of x over all processors in the current group.
Definition Process.cpp:145
static void barrier()
Synchronizes all processors in the current group (waits until all processors have reached the barrier...
Definition Process.cpp:133
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
SFichier is to the C++ ofstream class what Sortie is to the C++ ostream class.
Definition SFichier.h:29
SFichier(const char *name, IOS_OPEN_MODE mode=ios::out)
Definition SFichier.h:32
Separator for output streams.
Definition Separateur.h:29
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
Base class for output streams.
Definition Sortie.h:52
ostream & get_ostream()
Definition Sortie.h:64