DamBreak++ Physique Simulateur Supporte C++ Moderne
DamBreak++ Physique Simulateur
Je viens de compléter la première mise à niveau du Dam Break++ physique simulateur pour le support du C++ moderne. Cette tâche m’a demandé un effort soutenu et comme dans la plupart du temps on sous-estime le travail à réaliser. Depuis quelques années il y a eu beaucoup de développement et plusieurs prototypes. La tâche était d’abord de fusionner les différentes implémentations et de faire un tri. Nettoyage du code, des classes restructurées, fusionner les classes en double, et à réécrire certaines implémentations en utilisant les nouvelles fonctionnalités C++17/20. Plusieurs bogues ont été corrigés et un re-factoring a été effectué et est toujours en cours.
Ce travail m’a amené à repenser à l’architecture de l’application. Mon approche initiale était celle d’un (framework orientee-objet) couche abstraite de class à partir de laquelle on implémente les fonctionnalités de l’application. C++ moderne ajoute beaucoup de nouvelles fonctionnalités qui trouvent de belles applications dans le domaine de la programmation scientifiques (variadic template, move sémantique et plusieurs autres). Le concept de “forward reference”, permet d’implémenter une forme du polymorphisme appelé “perfect forwarding” (sélectionner la fonction selon le type d’arguments). Nombreuses sont les situations dans la programmation d’algorithmes (fonctions avec différentes signatures ou l’on doit choisir l’implémentation selon la signature (équivalent des méthodes virtuelles). Par exemple, dans l’environnement de programmation, support du “legacy code” ou la signature des fonctions sont des pointeurs. Mais les nouveaux algorithmes prennent comme arguments des tableaux numériques à virgule flottante très performant. Une application du “perfect forwarding”.
Je crois qu’une balance de fonctions et un design OO (Orientée-Objet) (framework avec une couche d’abstraction) est une approche à considérer. Dans bien des cas, en programmation scientifique les algorithmes peuvent être implémenter par des fonctions. Ceci m’a rappelé sur le savoir-faire en développement du logiciel. C’est un long processus d’itérations et de prototypages.
A Propos de DamBreak++ Physique Simulateur
Environnement de programmation qui utilise des pratiques modernes de développement logiciel dans le domaine la modélisation physique. Couche abstraite à partir de laquelle l’usager peut implémenter des algorithmes physiques afin de les valider sur le problème du bris de barrage uni-dimensionnel. Les projets de recherche industrielle, le physicien est souvent appelé à tester, prototyper afin d’expérimenter différents scénarios. Ce type d’environnement répond à ce besoin.
Resultats de Validation
Ci-dessous les resultats de validation.
Exemple de programmation
Ci-dessous des exemples tirés environnement de programmation. Comme je l’ai mentionné ci-haut, j’ai commencé à réécrire certains algorithmes avec les nouvelles fonctionnalités du langage moderne. Le processus de re-factoring est toujours en cours, présentement c’est la phase de prototypage.
C++20 Concept
C++20 ajoute le mot cle « Concept » qui est une contraint sur le parametre de la template.
template<typename Callable, typename ...Args>
decltype(auto) call( Callable&& aCalbl, Args&&... args)
{
std::invoke( std::forward<Callable>(aCalbl), // call passed to callable with
std::forward<Args>(args)...); // all additional passed args
}
// C++20 concept
template<typename T>
concept IsPointer = std::is_pointer_v<T>;
template<IsPointer T, auto N=101>
void hllSchemeFlux( T aU1, T aU2, T aFF1, T aFF2) // E. McNeil version
{
static_assert( N == vsc19::EMCNEILNbSections::value);
// do some numerical stuff (function-ptr from legacy code)
// by using "call" function above
EMcNeilCalculFF(aU1,aU2,aFF1,aFF2);
}
C++20 Range
Les “views” séquences de nombre que l’on peut traverser par itérations. La principale caractéristique de ce type, copie n’est pas dispendieuse et supporte la “move semantic”.
// C++20 ranges library
if( std::ranges::range<decltype(aA)>)
{
// pass an lvalue, std::span is used (view) cheap and should pass by value
auto w_rng = std::views::counted( std::ranges::begin(w_Avec), aA.size());
// Nujic paper(1995) physics consideration we need to take the average over cell
auto w_Avrg = Sfx::cell_face_average(w_rng); // pass a view (cheap to copy)
/// make the product of both average and derivative(computational node)
// Nujic algorithm to take account of some physics stuff ...
auto w_TermeS0 = w_Avrg * w_dxHvarray; // average times derivative (H_avg x d1xH)
return w_TermeS0;
}
Move semantic
Ci-dessous, “rvalue reference” permet d’eviter une copie qui peut être très couteux dans certains cas. La méthode “predictor” accepte une “prvalue: pure reading value” ou objet temporaire retourné par (getRhs()), ainsi on évite la copie du tableau.
// SWERHS shall be implemented in terms of numerical array for fast-floating point
void NujicIntegrator::predictor( SweRhsAlgorithm::SWERHS&& aRhs, const double aDt)
{
using namespace std;
// although pass an rvalue reference, within the function
// itself it is treated as an lvalue (cast to rvalue ref)
const auto w_rhs = std::move(aRhs);
...
}
...
void NujicIntegrator::step(SweRhsAlgorithm* aRhsAlgo, const double aDt)
{
//aRhsAlgo->calculate(m_prevState); ??? not really
//
switch (m_integratorStep)
{
case eIntegratorStep::predictor:
predictor(aRhsAlgo->getRHS(), aDt); //prvalue: pure reading value
break;
case eIntegratorStep::corrector:
corrector(aRhsAlgo->getRHS(), aDt); //prvalue: pure reading value
break;
default:
break;
}
}
Laisser un commentaire
Rejoindre la discussion?N’hésitez pas à contribuer !