TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Probleme_U.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 <Probleme_U.h>
17#include <Perf_counters.h>
18#include <ICoCoExceptions.h>
19#include <Ch_front_input_uniforme.h>
20#include <Ch_input_uniforme.h>
21#include <Champ_input_P0.h>
22
23#ifdef VTRACE
24#include <vt_user.h>
25#endif
26
27#include <Champ_Generique_base.h>
28#include <Convert_ICoCoTrioField.h>
29
30Implemente_base(Probleme_U,"Probleme_U",Objet_U);
31
32using ICoCo::WrongArgument;
33using ICoCo::TrioField;
34
36{
37 return os;
38}
39
41{
42 return is ;
43}
44
45/*! @brief This method is called once at the beginning, before any other one of the interface Problem.
46 *
47 * @throws WrongContext
48 */
52
53/*! @brief This method is called once at the end, after any other one.
54 *
55 * It frees the memory and saves anything that needs to be saved.
56 *
57 * @throws WrongContext
58 */
60{
61}
62
63/*! @brief Returns the present time.
64 *
65 * This value may change only at the call of validateTimeStep.
66 * A surcharger
67 *
68 * @return (double) present time
69 * @throws WrongContext
70 */
72{
73 return 0;
74}
75
76/*! @brief Compute the value the Problem would like for the next time step.
77 *
78 * This value will not necessarily be used at the call of initTimeStep,
79 * but it is a hint.
80 * This method may use all the internal state of the Problem.
81 *
82 * @param (stop) Does the Problem want to stop ?
83 * @return (double) The desired time step
84 * @throws WrongContext
85 */
86double Probleme_U::computeTimeStep(bool& stop) const
87{
88 stop=true;
89 return 0;
90}
91
92/*! @brief This method allocates and initializes the unknown and given fields for the future time step.
93 *
94 * The value of the interval is imposed through the parameter dt.
95 * In case of error, returns false.
96 *
97 * @param (double dt) the time interval to allocate
98 * @return (bool) true=OK, false=error, not able to tackle this dt
99 * @throws WrongContext, WrongArgument
100 */
102{
103 return false;
104}
105
106/*! @brief Validates the calculated unknown by moving the present time at the end of the time step.
107 *
108 * This method is allowed to free past values of the unknown and given
109 * fields.
110 *
111 * @throws WrongContext
112 */
116
117/*! @brief Tells if the Problem unknowns have changed during the last time step.
118 *
119 * @return (bool) true=stationary, false=not stationary
120 * @throws WrongContext
121 */
123{
124 return false;
125}
126
127/*! @brief Tells to the Problem that stationary is reached or not
128 *
129 */
131{
132}
133
134/*! @brief Aborts the resolution of the current time step.
135 *
136 * @throws WrongContext
137 */
141
142/*! @brief Reset the current time of the Problem to a given value.
143 *
144 * Particularly useful for the initialization of complex transients: the starting point of the transient
145 * of interest is computed first, the time is reset to 0, and then the actual transient of interest starts with proper
146 * initial conditions, and global time 0.
147 *
148 * @param[in] time the new current time.
149 * @throws ICoCo::WrongContext exception if called before initialize() or after terminate().
150 * @throws ICoCo::WrongContext exception if called inside the TIME_STEP_DEFINED context (see Problem documentation)
151 */
152void Probleme_U::resetTime(double time)
153{
154}
155
156/*! @brief In the case solveTimeStep uses an iterative process, this method executes a single iteration.
157 *
158 * It is thus possible to modify the given fields between iterations.
159 * converged is set to true if the process has converged, ie if the
160 * unknown fields are solution to the problem on the next time step.
161 * Otherwise converged is set to false.
162 * The return value indicates if the convergence process behaves normally.
163 * If false, the Problem wishes to abort the time step resolution.
164 *
165 * @param (bool& converged) It is a return value : true if the process has converged, false otherwise.
166 * @return (bool) true=OK, false=unable to converge
167 * @throws WrongContext
168 */
169bool Probleme_U::iterateTimeStep(bool& converged)
170{
171 return false;
172}
173
174/*! @brief Asks the problem to post-process its fields, probes, etc.
175 *
176 * In Probleme_U::run(), postraiter() is called at each time step with force=0
177 * and at the beginning and end of the computation with force=1.
178 * WEC: it would be good if, one day, postraiter were const.
179 *
180 * @param (force) 1=post-process unconditionally, 0=post-process if necessary.
181 * @return (0 on error, 1 otherwise.)
182 */
184{
185 return 0;
186}
187
188/*! @brief Should we print the execution statistics now?
189 *
190 */
192{
193 return 0;
194}
195
196/*! @brief Should we save the problem state to disk now?
197 *
198 */
200{
201 return 0;
202}
203
204/*! @brief Save the problem state to disk.
205 *
206 */
208{
209 return ;
210}
211
212
213/*! @brief WARNING:
214 *
215 * Everything that does not fit the normal Problem API goes here.
216 *
217 * Currently it updates boundary conditions and source terms, knowing
218 * that some of them fetch information from neighboring problems themselves...
219 *
220 * Work plan: everything in this method must be made independent of external
221 * state, and can then be merged into initTimeStep.
222 * The rest moves into the field exchange interface.
223 * This work will be done when updateGivenFields is empty and removed!
224 *
225 *
226 * @return (true=OK, false=error)
227 */
229{
230 return true;
231}
232
233
234/*! @brief This method is a sort of main() for the Problem. It can be used if the problem is not coupled with any other.
235 *
236 * (if it does not need any input field).
237 *
238 * @return (bool) true=OK, false=error
239 */
241{
242 // Force the post process task at the beginning of the run
243 Cerr<<"First postprocessing, this can take some minutes"<<finl;
244 postraiter(1);
245 Cerr<<"First postprocessing OK"<<finl;
246 bool stop=false; // Does the Problem want to stop ?
247 bool ok=true; // Is the time interval successfully solved ?
248
249 // Compute the first time step
250 double dt=computeTimeStep(stop);
251
252 statistics().end_count(STD_COUNTERS::computation_start_up);
253 // Print the initialization CPU statistics
254 statistics().print_TU_files("Computation start-up statistics");
255#ifdef VTRACE
256 //VT_USER_END("Initialization");
257 VT_BUFFER_FLUSH();
258 VT_ON();
259 VT_USER_START("Resolution");
260#endif
261 // Time step loop
262 long int tstep = 0;
263 statistics().start_timeloop();
264 while(!stop)
265 {
266 // Begin the CPU measure of the time step
267 statistics().start_time_step();
268 statistics().begin_count(STD_COUNTERS::timeloop);
269 ok=false; // Is the time interval successfully solved ?
270 // Loop on the time interval tries
271 while (!ok && !stop)
272 {
273
274 // Prepare the next time step
275 if (!initTimeStep(dt))
276 return false;
277
278 // Backup unknown fields if necessary
279 if (lsauv())
280 sauver();
281
282 // Solve the next time step
283 ok=solveTimeStep();
284
285 if (!ok) // The resolution failed, try with a new time interval.
286 {
288 dt=computeTimeStep(stop);
289 }
290 else // The resolution was successful, validate and go to the next time step.
292 }
293 if (!ok) // Impossible to solve the next time step, the Problem has given up
294 {
295 statistics().end_count(STD_COUNTERS::timeloop);
296 statistics().end_time_step(tstep);
297 break;
298 }
299
300 // Compute the next time step length
301 dt=computeTimeStep(stop);
302
303 // Stop the resolution if the Problem is stationnary
304 if (isStationary())
305 {
306 stop=true;
307 setStationary(stop);
308 }
309
310 std::string newDirectory = stop ? newCompute() : "";
311 if (!newDirectory.empty())
312 {
313 // ToDo: ameliorer le message
314 //if (!isStationary()) Process::exit("Error, the parametric problem is not stationary! Check the convergence.");
315 // Keep on the resolution if parametric variation in a new directory:
316 stop = false;
317 setStationary(stop);
318 setInputStringValue("SORTIE_ROOT_DIRECTORY", newDirectory);
319 resetTime(0.);
320 }
321 else
322 {
323 // Post process task (Force the post processing/prints at the end of the run (stop=1))
324 postraiter(stop);
325 }
326
327 // Stop the CPU measure of the time step and print:
328 if (limpr())
329 {
330 double temps = statistics().get_time_since_last_open(STD_COUNTERS::timeloop);
331 Cout << finl << "clock: Time of the last time step: " << temps << " s" << finl << finl;
332 }
333 tstep++;
334 statistics().end_count(STD_COUNTERS::timeloop);
335 statistics().end_time_step(tstep);
336#ifdef VTRACE
337 // Flush the buffer regulary to avoid setting VT_MAX_FLUSHES=0 variable...
338 VT_BUFFER_FLUSH();
339#endif
340 }
341 statistics().end_timeloop();
342#ifdef VTRACE
343 VT_USER_END("Resolution");
344 VT_OFF();
345#endif
346 statistics().print_TU_files("Time loop statistics");
347 return ok;
348}
349
350/*! @brief This method has the same role as the method run, but it stops when reaching the time given in parameter.
351 *
352 * If this time cannot be reached, the method returns false.
353 *
354 * @param (double time) time to reach
355 * @return (true=OK, false=error)
356 */
357bool Probleme_U::runUntil(double time)
358{
359 // Error if time is already past
360 if (time<presentTime())
361 return false;
362
363 bool stop=false; // Does the Problem want to stop ?
364 bool ok=true; // Is the time interval successfully solved ?
365
366 // Compute the first time step length
367 double dt=computeTimeStep(stop);
368 statistics().start_timeloop();
369
370 // Loop over time steps
371 while(!stop)
372 {
373 statistics().start_time_step();
374 statistics().begin_count(STD_COUNTERS::timeloop);
375 ok=false;
376
377 // Loop on the time interval tries
378 while (!ok && !stop)
379 {
380
381 // Do not go past time
382 if (presentTime()+dt>time)
383 dt=time-presentTime();
384
385 // Prepare the next time step
386 if (!initTimeStep(dt))
387 return false;
388
389 // Solve the next time step
390 ok=solveTimeStep();
391
392 if (!ok) // The resolution failed, try with a new time interval.
393 {
395 dt=computeTimeStep(stop);
396 }
397
398 else // The resolution was successful, validate and go to the
399 // next time step.
401 }
402 if (!ok) // Impossible to solve the next time step, the Problem has given up
403 break;
404
405 // time was reached
406 if (presentTime()==time)
407 return true;
408
409 // Compute the next time step length
410 dt=computeTimeStep(stop);
411
412 if (je_suis_maitre() && limpr())
413 {
414 double temps = statistics().get_time_since_last_open(STD_COUNTERS::timeloop);
415 Cout << finl << "clock: Total time of the time loop: " << temps << " s" << finl << finl;
416 }
417 statistics().end_count(STD_COUNTERS::timeloop);
418 postraiter(0);
419 }
420 statistics().end_timeloop();
421 statistics().print_TU_files("Time loop statistics");
422 return ok;
423}
424
425/*! @brief For possible re-implementation and unified call from python.
426 *
427 */
429{
430 bool converged = false;
431 bool ok = true;
432
433 while (!converged && ok)
434 {
435 ok= ok && updateGivenFields();
436 ok = ok && iterateTimeStep(converged);
437 }
438
439 return ok;
440}
441
442/*! @brief Returns the future time (end of current computing interval) This value is valid between initTimeStep and either
443 *
444 * validateTimeStep or abortTimeStep.
445 * A surcharger
446 *
447 * @return (double) future time
448 * @throws WrongContext
449 */
451{
452 return 0;
453}
454
455/*! @brief This method is used to find the names of input fields understood by the Problem
456 *
457 * @param (Noms) list of names where the Problem appends its input field names.
458 */
460{
461}
462
463/*! @brief This method is used to find in a hierarchy of problems the Champ_Input_Proto of a given name.
464 *
465 * Implementation is not optimal in 2 ways :
466 * - no error if two input fields have the same name.
467 * - no optimisation of the number of REF objects created and destroyed.
468 *
469 * @param (string name) name of the input field we are looking for
470 * @return (OBS_PTR(Field_base)) found <=> non_nul(), then points to a Champ_Input_Proto of that name.
471 */
472OBS_PTR(Field_base) Probleme_U::findInputField(const Nom& name) const
473{
475 return ch;
476}
477
478
479
480
481/*! @brief This method is used to find the names of output fields understood by the Problem
482 *
483 * @param (Noms) list of names where the Problem appends its output field names.
484 */
486{
487}
488
489OBS_PTR(Champ_Generique_base) Probleme_U::findOutputField(const Nom& name) const
490{
491 OBS_PTR(Champ_Generique_base) ch;
492 return ch;
493}
494
495
496
497/*! @brief This method is used to get a template of a field expected for the given name.
498 *
499 */
500void Probleme_U::getInputFieldTemplate(const Nom& name, TrioField& afield) const
501{
502 OBS_PTR(Field_base) ch=findInputField(name);
503 if (!ch)
504 throw WrongArgument(le_nom().getChar(),"getInputFieldTemplate",name.getString(),"no input field of that name");
505
506 // Due to the fact that we cannot make a reference to Champ_Input_Proto which is not an Objet_U...
507 Champ_Input_Proto * chip = dynamic_cast<Champ_Input_Proto *>(ch.operator->());
508 if (!chip)
509 throw WrongArgument(le_nom().getChar(),"getInputFieldTemplate",name.getString(),"field of this name is not an input field");
510
511 chip->getTemplate(afield);
512}
513
514/*! @brief This method is used to provide the Problem with an input field.
515 *
516 */
517void Probleme_U::setInputField(const Nom& name, const TrioField& afield)
518{
519 OBS_PTR(Field_base) ch=findInputField(name);
520 if (!ch)
521 throw WrongArgument(le_nom().getChar(),"setInputField",name.getString(),"no input field of that name");
522 if (!est_egal(afield._time1,presentTime()))
523 throw WrongArgument(le_nom().getChar(),"setInputField","afield","Should be defined on current time interval");
524 if (!est_egal(afield._time2,futureTime()))
525 throw WrongArgument(le_nom().getChar(),"setInputField","afield","Should be defined on current time interval");
526 if (strcmp(name.getChar(),afield.getCharName()))
527 throw WrongArgument(le_nom().getChar(),"setInputField","afield","Should have the same name as the argument name ");
528
529 // Due to the fact that we cannot make a reference to Champ_Input_Proto which is not an Objet_U...
530 Champ_Input_Proto * chip = dynamic_cast<Champ_Input_Proto *>(ch.operator->());
531 if (!chip)
532 throw WrongArgument(le_nom().getChar(),"setInputField",name.getString(),"field of this name is not an input field");
533
534 chip->setValue(afield);
535}
536
537void Probleme_U::getOutputField(const Nom& name, TrioField& afield) const
538{
539
540 OBS_PTR(Champ_Generique_base) ref_ch=findOutputField(name);
541 if (!ref_ch)
542 throw WrongArgument(le_nom().getChar(),"getOutputField",name.getString(),"no output field of that name");
543
544 const Champ_Generique_base& ch = ref_ch.valeur();
545 build_triofield(ch, afield);
546 afield.setName(name.getString());
547}
548
549// For now: set a field value provided the field has only one item.
550void Probleme_U::setInputDoubleValue(const Nom& name, const double val)
551{
552 OBS_PTR(Field_base) ch = findInputField(name);
553 if (!ch)
554 throw WrongArgument(le_nom().getChar(),"setInputDoubleValue",name.getString(),"no input field of that name");
555 if (ch->nb_comp() != 1)
556 throw WrongArgument(le_nom().getChar(),"getOutputDoubleValue",name.getString(),"invalid field size!!");
557
558 // Wa can not do a REF on Champ_Input_Proto which is not an Objet_U...
559 Champ_Input_Proto * chip = dynamic_cast<Champ_Input_Proto *>(ch.operator ->());
560 if (!chip)
561 throw WrongArgument(le_nom().getChar(),"setInputField",name.getString(),"field of this name is not an input field");
562 chip->setDoubleValue(val);
563}
564
565std::string Probleme_U::getOutputStringValue(const std::string& name)
566{
567 if(str_params_.count(name) == 0)
568 {
569 WrongArgument(name,"getOutputStringValue",name,"no string parameter with that name");
570 }
571 return str_params_[name];
572}
573
574void Probleme_U::setInputIntValue(const Nom& name, const int& val)
575{
576 // add value in ICoCoScalarRegister
577 reg_.setInputIntValue(name, val);
578}
579
580int Probleme_U::getOutputIntValue(const Nom& name) const
581{
582 return reg_.getOutputIntValue(name);
583}
584
586{
587 return reg_.checkOutputIntEntry(name);
588}
589
590double Probleme_U::getOutputPointValues(const Nom& name, const double x, const double y, const double z, int compo)
591{
592 std::vector<double> xx, yy, zz, vals;
593 xx.push_back(x);
594 yy.push_back(y);
595 zz.push_back(z);
596 getOutputPointValues(name, xx, yy, zz, vals, compo);
597 return vals[0];
598}
class Champ_Generique_base
This is the base class for all the Fields which can be written by a call to Problem::setInputField.
virtual void setValue(const TrioField &afield)=0
virtual void setDoubleValue(const double val)
virtual void getTemplate(TrioField &afield) const =0
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const char * getChar() const
Definition Nom.h:91
const std::string & getString() const
Definition Nom.h:92
An array of character strings (VECT(Nom)).
Definition Noms.h:26
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Probleme_U.
Definition Probleme_U.h:46
virtual void sauver() const
Save the problem state to disk.
virtual int postraiter(int force=1)
Asks the problem to post-process its fields, probes, etc.
virtual void getInputFieldsNames(Noms &noms) const
This method is used to find the names of input fields understood by the Problem.
virtual bool initTimeStep(double dt)
This method allocates and initializes the unknown and given fields for the future time step.
virtual std::string newCompute()
Definition Probleme_U.h:60
virtual OBS_PTR(Field_base) findInputField(const Nom &name) const
virtual void validateTimeStep()
Validates the calculated unknown by moving the present time at the end of the time step.
virtual int limpr() const
Should we print the execution statistics now?
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Probleme_U.h:109
virtual void setInputField(const Nom &name, const ICoCo::TrioField &afield)
virtual bool iterateTimeStep(bool &converged)
In the case solveTimeStep uses an iterative process, this method executes a single iteration.
virtual void setInputDoubleValue(const Nom &name, const double val)
virtual void getOutputPointValues(const Nom &name, const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z, std::vector< double > &vals, int compo)
Definition Probleme_U.h:74
virtual void setInputStringValue(const std::string &name, const std::string &val)
Definition Probleme_U.h:88
virtual void terminate()
This method is called once at the end, after any other one.
virtual void abortTimeStep()
Aborts the resolution of the current time step.
virtual double futureTime() const
Returns the future time (end of current computing interval) This value is valid between initTimeStep ...
virtual bool checkOutputIntEntry(const Nom &name) const
virtual bool runUntil(double time)
This method has the same role as the method run, but it stops when reaching the time given in paramet...
virtual int lsauv() const
Should we save the problem state to disk now?
virtual bool run()
This method is a sort of main() for the Problem. It can be used if the problem is not coupled with an...
virtual bool solveTimeStep()
For possible re-implementation and unified call from python.
virtual std::string getOutputStringValue(const std::string &name)
ScalarRegister reg_
Definition Probleme_U.h:113
virtual bool isStationary() const
Tells if the Problem unknowns have changed during the last time step.
virtual double presentTime() const
Returns the present time.
virtual void setStationary(bool)
Tells to the Problem that stationary is reached or not.
virtual void getOutputFieldsNames(Noms &noms) const
std::map< std::string, std::string > str_params_
Definition Probleme_U.h:114
virtual void setInputIntValue(const Nom &name, const int &val)
virtual int getOutputIntValue(const Nom &name) const
virtual void getOutputField(const Nom &nameField, ICoCo::TrioField &afield) const
virtual void resetTime(double time)
Reset the current time of the Problem to a given value.
virtual void getInputFieldTemplate(const Nom &name, ICoCo::TrioField &afield) const
virtual bool updateGivenFields()
WARNING:
virtual void initialize()
This method is called once at the beginning, before any other one of the interface Problem.
virtual double computeTimeStep(bool &stop) const
Compute the value the Problem would like for the next time step.
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
Base class for output streams.
Definition Sortie.h:52