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;
    }
  }

en savoir plus

0 réponses

Laisser un commentaire

Rejoindre la discussion?
N’hésitez pas à contribuer !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *