Anomalie #309
Fonctions externes
Ajouté par Frank Petitjean il y a environ 3 ans. Mis à jour il y a presque 3 ans.
Description
Bonjour Gérard,
J'ai écrit un cas test élémentaire d'utilisation d'une fonction externe Python. l'ensemble fonctionne très bien sur un maillage de 1 élément, de 2 éléments mais plus pour 10 éléments.
Dans ce dernier cas Herezh écrit et lit correctement sur les pipes IN OUT pour le 1er point d'intégration. Au deuxième pti il écrit sur PipeOUT une chaine vide (dixit le script Python) et se met en attente.
Je sais qu'il t'est pas facile de fonctionner sous Linux et avec Python. Peux-tu éventuellement reproduire ce cas sous MacOS et en C++ ?
Ci-joint les fichiers.
Merci pour ton aide,
Frank
Fichiers
maillage_2.her (2,8 ko) maillage_2.her | Frank Petitjean, 08/11/2021 10:35 | ||
communication_herezh_pipe.py (2,26 ko) communication_herezh_pipe.py | Frank Petitjean, 08/11/2021 10:35 | ||
maillage_10.her (4,92 ko) maillage_10.her | Frank Petitjean, 08/11/2021 10:35 | ||
modele.CVisu (7,7 ko) modele.CVisu | Frank Petitjean, 08/11/2021 10:35 | ||
modele.info (1,7 ko) modele.info | Frank Petitjean, 08/11/2021 10:35 | ||
modele10.log (3,51 ko) modele10.log | Frank Petitjean, 08/11/2021 10:35 | ||
modele_2.log (27,5 ko) modele_2.log | Frank Petitjean, 08/11/2021 10:35 | ||
fonction_externe copie.zip (43,5 ko) fonction_externe copie.zip | Gérard Rio, 12/11/2021 10:01 | ||
fctExterne.info (5,54 ko) fctExterne.info | le .info avec l'appel de la fonction externe | Gérard Rio, 14/11/2021 09:41 | |
communication_herezh_pipe_MR.py (4,98 ko) communication_herezh_pipe_MR.py | le fichier python | Gérard Rio, 14/11/2021 09:41 |
Mis à jour par Frank Petitjean il y a environ 3 ans
Gérard,
J'ai partiellement résolu le problème. La gestion des pipes dans Herezh n'est pas en cause. Le problème vient de la façon dont est géré le multithreading dans Python car tout fonctionne bien si je lance séparément Herezh et Python dans 2 fenêtres de commande distinctes. Je vais essayer d'utiliser le multiprocessing dans Python au lieu du multithreadind.
Sinon les fonctions externes si top !
Frank
Mis à jour par Gérard Rio il y a environ 3 ans
- Statut changé de Nouveau à En cours
le multithreading est a priori très intéressant car il évite le passage de paramètre mais il peut induire des effets de "goulots d'étranglement" lors d'un accès multiple à une même zone mémoire: c'est classique.
Le MPI permet de séparer les zones mémoires mais implique des passages de paramètres et cela ne supprime pas complètement les effets de goulots ... cependant on a l'impression que l'on peut mieux gérer (?) ces effets ...
Bon courage
Mis à jour par Frank Petitjean il y a environ 3 ans
J'y vois maintenant plus clair. J'ai en fait 4 méthodes possibles:
1. Lancer Herezh et la fonction_ext.py dans 2 fenêtres de commande différentes (i.e. 2 process séparés)
2. Lancer les 2 process successivement dans un main.py en ajoutant "&" pour Herezh pour libérer le process
3. Lancer 2 process en parallèle dans main.py (module mutliprocessing)
4. Lancer 2 threads en parallèle dans main.py (module mutlithreading)
C'est 4 méthodes fonctionnent et donnent le même résultat (la 2e est plus simple à mettre en œuvre). Elles sont toutes les 4 plus ou moins sensibles à ce problème de goulot d'étranglement. Dans mon cas test élémentaire, et quelque soit la méthode, il est nécessaire d'introduire une temporisation de 1/100 de seconde max dans le fonction externe pour freiner chaque appel. Sinon Herezh s'arrête en cours d'itération.
Je suis en train d'écrire la fonction externe pour mon calcul d'effet du vent. Compte tenu de la taille du problème EF et des temps de calcul dans la fct externe il est probable que la temporisation ne soit plus nécessaire.
Merci pour tes encouragements !
Frank
Mis à jour par Frank Petitjean il y a environ 3 ans
Gérard,
Après pas mal de développements en Python j'ai obtenu la bonne fonction externe. Pour passer du champ de pression sur les tria du maillage CFD je dois faire 2 interpolations successives, la première sur une grille non structurée et la seconde pour construire une fonction d'interpolation p(theta, phi) qui est chargée dans la fonction externe. Les résultats Herezh obtenus sur le BSO avec le seul chargement de pression et les nœuds bloqués ne donnent pas du tout les bonnes valeurs de pression, ce qui est confirmé dans le .log avec l'affichage 8. Même en imposant une valeur constante dans la fonction externe elle n'est pas lue correctement.
Pour comprendre j'ai repris mon cas test élémentaire avec une pression constante avec des maillages plus importants (1000 et 10000 quadrangles). Le pipeOUT fournit les bonnes valeurs mais le pipeIN récupère n'importe quoi. Pour que cela fonctionne il faut augmenter temps de latence dans le fichier Python jusqu'à une seconde pour le gros maillage (la pression ne s'applique que sur une face). Cette temporisation rend l'utilisation de fonctions externes inexploitable. Le comportement est identique avec les 4 méthodes indiquées plus haut.
Question : as-tu déjà testé les fonctions externes pour appliquer une pression sur un gros maillage ? Le fonctionnement des pipes est peut-être différent lorsque les 2 programmes sont écrits en C++ ?
L'utilisation d'un champs de valeurs fonctionne bien et c'est apriori une bonne méthode pour moi car il n'y a pas de dépendance de la pression avec le déplacement des noeuds (je n'ai qu'un résultats CFD). Malheureusement avec cette méthode je ne peux pas faire varier la pression en fonction de la normale aux éléments pour le contrôle des lobes inversés. Résultat le petit déséquilibre amené par cet effet du vent sur la surpression totale suffit à créer une double peau ! Résultat déjà observé avant la mise au point de cette méthode de contrôle.
La seule solution fonctionnelle actuellement est celle que j'ai mise en œuvre en premier. Elle consiste à construire une fonction analytique approchée p(theta, phi) qui est ensuite introduite dans Herezh via une fonction nD. Cela permet d'appliquer sur la pression totale la pénalisation par le produis scalaire pour le contrôle des lobes.
Je suis quand même bien déçu de ne pas pouvoir aller plus loin en utilisant une fonction externe ! Ce n'est pas le fait d'Herezh bien sûr mais je tenais à te tenir informé de mes déboires...
Frank
Mis à jour par Gérard Rio il y a environ 3 ans
Bonjour Frank,
quelques questions pour bien comprendre:
- est-ce que tu as essayé avec un seul processus en python, ceci pour être sûr qu'il n'y a pas deux process qui écrivent sur le même pipe en même temps ?
- je ne comprends pas pourquoi tu as besoin d'une temporisation: normalement l'écriture s'effectue par défaut "sans attente", c-a-d que le programme (python ou herezh) passe les infos à un "interface driver" (qui a la charge d'écrire dans le pipe) et il continue. Par contre en lecture, tant que la lecture n'est pas finie, le programme lit...
Du coup, tant qu'herezh n'a pas demandé une nouvelle information il faut que le programme python attende. De la même manière, tant qu'herezh n'a pas lu la totalité de l'info qu'il attend, il ne va pas plus loin.
Intuitivement, j'ai l'impression que c'est là qu'il faut chercher.
- je n'ai jamais fait de test de fonction externe avec un maillage très grand. Je vais le faire.
Mis à jour par Frank Petitjean il y a environ 3 ans
Oui il n'y a qu'un processus qui écrit puisque la fonction qui lit et écrit n'est appelée qu'une fois. Il y a une simple boucle "tant que" avec une déclaration des pipes l'un en lecture et l'autre en écriture.
J'ai repris la méthode proposée par Hugo. Il avait lui aussi remarqué qu'une temporisation était nécessaire.
Dans la mesure où le process attend la fin de la lecture/écriture pour poursuivre il ne devrait pas y avoir de problème en effet. Je pourrais essayer avec 2 programmes Python exécutés en parallèle pour voir s'il y a ce genre de problème.
Mis à jour par Gérard Rio il y a environ 3 ans
- Fichier fonction_externe copie.zip fonction_externe copie.zip ajouté
- % réalisé changé de 0 à 50
Bonjour Frank,
je viens de faire un essai avec un maillage de 1000 éléments. A priori tout fonctionne correctement.
Il s'agit d'un essai de compression simple. J'impose une pression qui augmente avec le nombre d'incrément.
Je retrouve en résultat que j'impose (la contrainte == la pression imposée).
Je te joins les fichiers de calcul.
Tu peux peut-être vérifier que ce calcul fonctionne aussi chez toi. Ensuite il faudrait peut-être regarder de plus près au niveau équivalence: C++ et python.
Mis à jour par Frank Petitjean il y a environ 3 ans
Merci Gérard, c'est une bonne chose que cela fonctionne en C++. Difficile pour moi de rentrer dans le détail du programme. Ma culture C remonte à mes années de fac et encore sans la couche objet++. Il faudrait que je puisse m'approprier ce cas test et le traduire en Python avec différentes façons des gérer les pipes, en espérant qu'une fonctionne correctement. Sinon passer au C++.
Je vais demander à RTime de me payer une formation ;-)
Frank
Mis à jour par Gérard Rio il y a environ 3 ans
- Fichier fctExterne.info fctExterne.info ajouté
- Fichier communication_herezh_pipe_MR.py communication_herezh_pipe_MR.py ajouté
Bonjour Frank,
Laurent Mahéo a écrit un programme python qui permet d'alimenter une fonction externe d'Herezh, ceci pour l'utilisation dans un potentiel hyperélastique. Pour info, ce référer au ticket #264
J'ai juste un peu modifié le programme de Laurent pour l'adapter à ton problème et cela fonctionne (a priori): je retrouve les mêmes résultats qu'avec le programme C++
Il n'y pas pas de temporisation et le calcul de test concerne un maillage 1000 éléments.
Je te joins le .info et le fichier python.
Peut-être que tu peux tester ?
Mis à jour par Frank Petitjean il y a environ 3 ans
Bonjour Gérard,
J'ai repéré ce que le script Python de Laurent avait de différent du mien. A chaque boucle il ouvre les pipes et ferme de suite après. Les instructions open et close étant au plus près l'une de l'autre. J'ai reproduit ce schéma dans mon script et... ça fonction parfaitement sans temporisation !!! C'était donc bien un problème de gestion des pipes dans mon script.
Avec cette correction, le process Python reste en attente de lecture du pipeOUT après la fin normal du calcul Herezh. Est-il possible que Herezh renvoe une chaine vide en fin de calcul de sorte à pouvoir sortir de la boucle while ?
Je n'ai pas repéré comment tu arrêtes ton programme en C++. Il y a bien une instruction "try" mais elle ne me semble pas faite pour ça.
Un grand merci pour ton aide, même en Python tu me débloques ;-)
Frank
Mis à jour par Gérard Rio il y a environ 3 ans
- % réalisé changé de 50 à 90
Bonjour Frank,
je suis content que cela fonctionne !!
Pour l'instant je n'ai pas trouvé quelque chose de simple pour arrêter le prog externe. Le pb est qu'une fonction externe n'a pas d'info particulière sur le déroulement global d'Herezh. Il faudrait donc qu'à la fin, Herezh appel spécifiquement les fonctions externes pour fermer les pipes, mais Herezh globalement ne pilote pas directement les fonctions externes, celles-ci sont appelées directement par les classes utilisatrices.
Bon, ceci étant je pourrai introduire une méthode spécifique, mais je ne sais pas si c'est très cohérent. De plus je trouve intéressant de pouvoir lancer plusieurs fois Herezh en utilisant la même fonction externe, donc sans avoir à relancer la fonction externe...
Du coup, pour l'instant j'ai bien envie de laisser tel quel: dans mes calculs je lance une fois la fonction externe, et ensuite je ne m'en occupe plus durant plusieurs lancement et arrêt d'Herezh ...
bon... en espérant que ce n'est pas rédhibitoire pour toi !!
Mis à jour par Frank Petitjean il y a environ 3 ans
Je comprends les difficultés dans Herezh. C'est pas un pb pour moi, j'avais juste l'envie de bien faire les choses et de ne pas arrêter brutalement le programme.