TP6 : couplage et hack de stardis pour y développer ses propres couplages
Voir le TP1 pour la prise en main du système d'exploitation EDIX.
Les commandes suivantes sont identiques à celles du début du TP1.
. /home/lafrier/star-build/local/etc/stardis.profile
mkdir TP6
cd TP6
TP6 - Partie 1 : explication des couplages dans Stardis
Intention : le modèle physique a été présenté en introduction. Ici on invite
le praticien à ouvrir le code pour se donner confiance sur ce qui est fait.
Partie 1.1 : partie théorique
Ajouter des informations complémentaires à l'introduction.
Introduire à cette occasion l'idée qu'il existe deux marches conductives
implémentées : delta-sphères et Walk-on-Spheres. Le Walk-on-sphere est plus
lisible et sera modifié dans le second exercice de ce TP6.
Prendre le temps d'expliquer la double randomisation au niveau d'une paroi
solide-solide puis solide-fluide.
Partie 1.2 : implémentation
Expliquer rapidement l'édifice stardis en deux parties : un solveur et un
applicatif, qui reposent sur des bibliothèques tierces (ex : génération de
nombres aléatoires). En particulier, ils contiennent :
solveur : espaces de chemins, différents types d'observable (point sonde,
image, etc) ...applicatif : gestion des entrées / sorties utilisateur ...
Les deux sont installés via star-build qui gère automatiquement
l'installation de toutes les dépendances. L'exercice 3 de ce TP traite
spécifiquement de l'installation de stardis, mais nous n'en avons pas besoin
dans ce premier exercice. Ici, on s'intéresse en particulier au solveur. On
va aller regarder comment les espaces de chemins sont implémentés.
Le code source peut être lu dans le dossier défini ci-dessous :STARDIS_SRC=/home/lafrier/star-build/cache/stardis-solver/0.16/src/
Avant propos :
Code C89 avec un paradigme de programmation structurée.
On suppose que le lecteur est familier du langage C, en particulier des types
structurés et du concept de pointeur et de pointeur de fonction (faire
référence au "Livre de programmation littéraire" pour cela).
Sinon on conseille le livre "Le langage C Norme ANSI - 2nde édition" de
Kernighan et Ritchie. Ici on a une difficulté en plus qui est la
généricité : les fonctions appelées par la macro XD(), seront expansées par le
préprocesseur avec les termes _2d et _3d pour former deux nouvelles fonctions.
TODO
Faire un point avancé sur cela dans le "Livre de programmation littéraire".
Les éléments qu'il semble important de parcourir :
Partie 1.2.1 : fonction principale avec boucle MC et moyenne des réalisations
On choisit l'exemple de la fonction solve_one_probe dans le fichier
sdis_solve_probe_Xd.h. On fait ce choix parce que cette fonction est simple à
lire (par opposition à solve_probe présentée ensuite).
vim "${STARDIS_SRC}"/sdis_solve_probe_Xd.h
Globalement, toujours la même structure :
static res_T
XD(solve_one_probe)
(struct sdis_scene* scn,
struct ssp_rng* rng,
const struct sdis_solve_probe_args* args,
struct accum* acc_temp,
struct accum* acc_time)
La fonction solve_one_probe prend 5 paramètres en entrée, tous avec des types
structurés internes au solveur ; elle renvoie une valeur de type res_T qui
indique s'il y a eu une erreur d'exécution ou pas :
- scn pointe vers une structure contenant les informations liées à la scène,
- rng pointe vers une structure permettant la génération de nombres
aléatoires, - sdis_solve_probe_args pointe vers une structure contenant les informations
relatives à la simulation, - acc_temp pointe vers une structure qui stocke des informations sur les
poids des réalisations pour estimer la température et la barre d'erreur
associée, - idem pour acc_time concernant le temps de calcul.
Les accumulateurs sont d'abord vidés.
Pour chaque réalisation (FOR_EACH) :
- le temps initial est enregistré,
- un temps échantillonné sur la période d'intégration temporelle
- la fonction probe_realisation appelée avec l'argument realis_args dont les
champs ont été remplis. - le temps d'éxécution est calculé
- les accumulateurs mis à jour avec le poids du chemin (température atteinte)
et le temps de calcul
Partie 1.2.2 : pour chaque réalisation, comment est construit un chemin ?
par un appel de fonction, jusqu'à T->done == 1.
cat "${STARDIS_SRC}"/sdis_realisation_Xd.h
Regarder la fonction XD(probe_realisation).
D'abord, le chemin est initialisé (temps et position de départ).
En fonction du milieu dans lequel se trouve le point sonde, le chemin
commencera en mode convectif ou bien conductif. Ces informations sont
enregistrées.
Si la condition initiale est atteinte, on ne lance pas le calcul. Sinon appel
à XD(sample_coupled_path). Le poids de MC sera le champ value de T.
Allons voir cette fonction sample_coupled_path.
On voit que, tant que le chemin n'est pas fini, ce qui se traduit par le champ
done de la structure pointée par T n'est pas mis à 1 : while(!T->done) {...}
Alors, on répète la même action :
- On appelle la fonction
T->func(scn, ctx, rwalk, rng, T)pour construire une
portion de chemin. - Le
do {} while()sert à recommencer l'action si la portion de chemin a été
rejetée. - On identifie ensuite le mode physique dans lequel le chemin se trouve
(conduction / convection ou rayonnement).
Partie 1.2.3 : construction d'une portion de chemin
Quelle que soit la physique, la fonction qui construit la portion de chemin a
toujours la même forme :
- Récupérer des paramètres de contexte sur l'endroit où se trouve le chemin,
- Calculs de jeux de probabilité basé sur les paramètres physiques
- Tirage aléatoire selon ce jeu de probabilité pour déterminer la suite du
chemin (spatio-temporel) - Si la condition initiale est atteinte, T->done = 1;
- Mise à jour du chemin, en particulier de T->func pour le prochain mode
physique
L'exercice consiste ici à faire le parallèle entre l'algorithme et le code
sur une seule des physiques. On choisit le cas de l'interface fluide-solide.
Ci-dessous, on pointe les fonctions implémentant les chemins dans les autres
physiques.
En fonction de la physique,
- convection :
sdis_heat_path_convective_Xd.h:XD(convective_path) - rayonnement :
sdis_heat_path_radiative_Xd.h:XD(radiative_path) - conduction :
XD(conductive_path)
C'est en fait
sdis_heat_path_conductive.c:conductive_path_3d
qui est appelée, et qui redirige vers les deux marches distinctes :
sdis_heat_path_conductive_wos_Xd.h:XD(conductive_path_wos)
sdis_heat_path_conductive_delta_sphere_Xd.h:
XD(conductive_path_delta_sphere) - interface :
sdis_heat_path_boundary_Xd.h:XD(boundary_path)
cette fonction renvoie ensuite vers- fluide-solide :
sdis_heat_path_boundary_Xd_solid_fluid_picard1.h:
XD(solid_fluid_boundary_picard1_path)
On expliquera Picard dans le TP7. - interface solide-solide :
sdis_heat_path_boundary_Xd_solid_solid.h:XD(solid_solid_boundary_path)
- fluide-solide :
On présente maintenant le cas de l'interface fluide-solide. Beaucoup de
choses ! Donc on va guider la lecture en colorant les parties à commenter.
L'objectif n'est pas que l'étudiant comprenne les détails, mais qu'il sache
qu'il peut se référer au code, le lire et le comprendre en ayant le modèle
physique à côté.
vim "${STARDIS_SRC}"/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h
Les éléments à mettre en couleur dans l'énoncé du TP :
h_conv = interface_get_convection_coef(interf, frag);
h_cond = lambda / delta_m;
h_radi_hat = 4.0 * BOLTZMANN_CONSTANT * ctx->That3 * epsilon;
...
h_hat = h_conv + h_cond + h_radi_hat;
...
p_conv = h_conv / h_hat;
p_cond = h_cond / h_hat;
...
/* Handle the net flux if any */
res = XD(handle_net_flux)(scn, &handle_net_flux_args, T);
/* Handle the external net flux if any */
res = XD(handle_external_net_flux)(scn, rng, &handle_external_net_flux_args, T);
...
/* Null collision */
for(;;) {
r = ssp_rng_canonical(rng);
...
/* Switch in convective path */
if(r < p_conv) {
T->func = XD(convective_path);
...
break;
}
/* Switch in conductive path */
if(r < p_conv + p_cond) {
...
res = XD(solid_reinjection)(scn, enc_ids[solid_side], &solid_reinject_args);
...
break;
}
/* Sample a radiative path and get the Tref at its end. */
...
res = XD(radiative_path)(scn, ctx, &rwalk_s, rng, &T_s);
/* Get the Tref at the end of the candidate radiative path */
res = XD(rwalk_get_Tref)(scn, &rwalk_s, &T_s, &Tref_s);
h_radi = BOLTZMANN_CONSTANT * epsilon *
( Tref*Tref*Tref
+ Tref*Tref * Tref_s
+ Tref * Tref_s*Tref_s
+ Tref_s*Tref_s*Tref_s);
p_radi = h_radi / h_hat;
if(r < p_conv + p_cond + p_radi) { /* Radiative path */
*rwalk = rwalk_s;
*T = T_s;
break;
/* Null collision: the sampled path is rejected. */
} else {
...
}
}
Astuce - Comment naviguer en autonomie ?
Utiliser l'outil grep pour rechercher la définition d'une structure dans tout
l'édifice stardis.
"Point théorique" sur les notions :
- d'édition de code source, édition du fichier source par le programmeur ;
- compilation du code source en un code interprêtable pour la machine.
A cette étape il faut que les librairies statiques soient identifiées. - exécution de ce code interprêtable par la machine.
Il faut spécifier le chemin vers cet exécutable par exemple./a.out,
ou que l'exécutable soit placé dans les dossiers parcourus par le shell
(par exemple /usr/local/) ou encore enrichir ces dossiers parcourus avec
le dossier courant (c'est la stratégie utilisée lorsque l'on fait
. path-to/local/etc/stardis.profile).
Ce point est nécessaire ici, même si ces concepts étaient déjà
nécessaires pour le TP3, parce que ce TP6 est tourné vers le développement.
TP6 - Partie 2 : propriétés programmables
Avant d'entrer dans le fonctionnement du hack de stardis, on va présenter
les propriétés programmables. On peut déjà faire beaucoup de choses avec
les propriétés programmables, notamment faire varier de façon
spatio-temporelle certains paramètres des conditions limites. Vous avez
déjà croisé un exemple dans le TP2 : celui de l'insensibilité du temps de
calcul au raffinement de la finesse de description temporelle des données.
Partie 2.1 : comprendre et faire tourner
Bibliothèque fournie par l'utilisateur au logiciel stardis, qui seront
appelées pendant la simulation MC. Il faut donc que les fonctions dont
stardis a besoin soient implémentées. Elles sont définies dans le fichier
suivant :
vim /home/lafrier/star-build/local/include/stardis/stardis-prog-properties.h
Ce fichier commence par définir les fonctions obligatoires à toute
propriété programmable, puis celles qui concernent chaque type de propriété
programmable. Un exemple est donné ici :
vim "${DEMONSTRATEUR_2}"/TP6/src/proprietes_programmables/src/tbound.c
Vous voyez que toutes ces fonctions sont bien définies. Dans cet exemple,
la température renvoyée (stardis_boundary_temperature) est exactement
celle qui est lue via stardis_create_data.
L'utilisation de cette bibliothèque comme propriété programmable se fait
dans le fichier model.txt en deux temps :
vim "${DEMONSTRATEUR_2}"/TP6/src/proprietes_programmables/scene/model_prog.txt
- Import de la bibliothèque programmable, elle est associée à un nom.
Elle est éventuellement initialisée si la bibliothèque a des variables
internes.
PROGRAM TBOUND libtbound_demonstrateur.so - Définition de conditions limites comme programmables, via les mots clés
"*_PROG" (voir manuel de stardis-input).
Celles-ci peuvent nécessiter des arguments, qui sont récupérés et passés
à la fonctionstardis_create_data
T_BOUNDARY_FOR_SOLID_PROG TEMP TBOUND left_bc.stl PROG_PARAMS 310
^^^
paramètres de la propriété programmable (ici un seul)
Compilation :
On va maintenant compiler cette bibliothèque de fonction programmable pour
que vous puissiez la modifier ensuite.
Ici nous utilisons l'ancien système de compilation, basé sur cmake et qui
repose à l'heure actuelle sur Makefile (et pkgconfig) plutôt.
TODO
A terme, Makefile ?
On commence par réaliser une copie locale des propriétés programmables :
cd TP6
cp -r "${DEMONSTRATEUR_2}"/TP6/src/proprietes_programmables .
cd proprietes_programmables
ls
Observer l'organisation avec les répertoires :
src/ : contient les sources de la bibliothèque de propriétés
programmablescmake/ : contient le fichier CMake qui va permettre la compilation
de la bibliothèquescene/ : contient un exemple de scène utilisant la bibliothèque de
propriétés programmables
On va maintenant créer le répertoire build dans lequel on compilera et
installera la bibliothèque.mkdir build cd build
On localise les bibliothèques dont on aura besoin :
. /home/lafrier/star-build/local/etc/stardis.profile
Procédure pour compiler les propriétés programmables :
cmake ../cmake -DCMAKE_INSTALL_PREFIX=local
installation des propriétés programmables dans le répertoire local :
make install
Observer la création du répartoire "local" :
ls
ls local/
ls local/lib/
Observer que la bibliothèque a bien été installée. Afin d'ajouter cette
bibliothèque à la variable d'environnement utilisée par l'éditeur de liens :
LD_LIBRARY_PATH=$(pwd)/local/lib:${LD_LIBRARY_PATH}
Il n'y a besoin de le faire qu'une seule fois.
Exécution :
cd ../scene/
ls
Il y a deux fichiers décrivant deux systèmes physiques identiques, l'un
utilisant les propriétés programmables ("model_prog.txt") et l'autre non
(model.txt). Observer que c'est bien le cas :
vim model.txt
vim model_prog.txt
Vérifier que le résultat est le même :
stardis -M model.txt -p 0.5,0.5,0.5
stardis -M model_prog.txt -p 0.5,0.5,0.5
Ici on obtient exactement le même résultat. Dans la suite, on réalisera
des images infrarouges pour visualiser aussi les conditions limites.
stardis -M model_prog.txt \
-R spp=4:img=100x100:fov=30:pos=-2,-2,2:up=0,0,1:tgt=0.5,0.5,0.5 > basic.ht
htpp -f -o basic.ppm -v -m default basic.ht
feh basic.ppm
Partie 2.2 : variation des propriétés spatiales
Note : c'est volontaire de laisser l'étudiant naviguer dans l'arborescence
et comprendre par lui-même comment modifier les sources, recompiler,
re-exécuter, etc.
Dans la fonction stardis_boundary_temperature de src/tbound.c, remplacez la
ligne return bound->temp; qui renvoie la constante lue par la fonction
suivante :
return bound->temp + 3.0 * \
( sin(2frag->P[0]) + sin(2frag->P[1]) + sin(2*frag->P[2]));
Recompilez et lancez maintenant le calcul d'une image infrarouge.
TODO
Attention avec la version 0.16 de stardis-solveur : la face apparaît
complètement noire et on ne voit donc pas ces variations spatiales.
Il faut la version develop de stardis-solveur pour le moment.
stardis -M model_prog.txt \
-R spp=4:img=100x100:fov=30:pos=-2,-2,2:up=0,0,1:tgt=0.5,0.5,0.5 > prog.ht
htpp -f -o prog.ppm -v -m default prog.ht
feh prog.ppm
Vous devez observer que la température imposée sur la face gauche varie
spatialement.
Partie 2.3 : variations temporelles
Partie 2.3.1 : construisez en autonomie un exemple avec un cube MINCE chaud
qui est plongé dans un milieu à température imposée plus froide
Supprimez tout rayonnement en mettant Tref = 0. Observez l'évolution
temporelle de la température de surface du cube. Vous devriez obtenir une
courbe exponentielle.
Aide : vous n'avez pas besoin des propriétés programmables pour cela, vous
pouvez vous inspirer des scripts gnuplot du TP4.
Partie 2.3.2 : que se passe-t-il si ce h est maintenant sinusoïdal ?
Vous pourrez par exemple choisir la fonction $h_c * (1 + 0.9 * \sin(t))$
et modifier le fichier src/hbound.c
Partie 2.3.3 : que se passe-t-il si le solide n'est plus mince ?
Corrections :
Les fichiers corrigés sont donnés dans le dossier
proprietes_programmables_correction.
Correction 2.3.1 :
cd ..
cp -r scene scene_convection
cd scene_convection
Remplir le modèle sans propriétés programmables pour répondre à la
consigne :
vim model.txt
Tracer une courbe exponentielle :
cp "${DEMONSTRATEUR_2}"/TP4/src/vary_time.sh .
sh vary_time.sh
Corrections 2.3.2 et 2.3.3 :
Implémentation de la propriété programmable.
Remplacer stardis_convection_coefficient dans hbound.c par
return bound->hc * (1.0 + 0.9555 * sin(frag->time));
Le champ time de la structure stardis_interface_fragment est donné dans
stardis-prog-properties.h :
vim ../src/hbound.c
Compilation :
cd ../build
make install
cd ../scene_convection
Exécution :
vim model_prog.txt
Appeler la fonction programmable, libhbound_demonstrateur.so
Consulter le manuel de stardis-input (man stardis-input) pour utiliser
cette propriété programmable en tant que condition limite :
H_BOUNDARY_FOR_SOLID_PROG ...
Exécuter stardis et tracer un graphique :
cp vary_time.sh vary_time_prog.txt
vim vary_time_prog.sh
Ajouter "_prog" à différents endroits pour lancer stardis sur model_prog.txt
mais aussi sauvegarder les données et le script gnuplot dans de nouveaux
fichiers. Choisissez bien la plage temporelle sur laquelle réaliser les
simulations.
Analyse :
sh vary_time_prog.sh
TODO
Si vous avez choisi un nombre de Biot suffisamment faible, alors vous verrez
une exponentielle, sinon vous observez que la température remonte ...
En fait, lorsque h est proche de 0, la température de surface augmente car le
coeur du solide est chaud, la température de surface est par contre refroidie
lorsque h augmente, la température du fluide extérieur étant plus faible.
Pour se convaincre de ces arguments, vous pourriez tracer la température dans
une coupe en fonction du temps.
On peut ici illustrer avec les images
proprietes_programmables_correction/scene_corr/graphique_*.png
Partie 2.4 : pour aller plus loin, faite en sorte que l'utilisateur spécifie
la fréquence du signal sinusoidal
Correction :
- TP6/src/proprietes_programmables_correction/src/hbound_frequence.c :
lecture de l'argument 6 dans la fonctionstardis_create_data, création
d'un champ dans la structuremy_hboundpour le stockage de cette
information, ensuite utilisée pour calculer le coefficient h dans la
fonctionstardis_convection_coefficient - TP6/src/proprietes_programmables_correction/cmake/CMakeList.txt : ajout
d'un nouvel exécutable à la compilation - TP6/src/proprietes_programmables_correction/scene_corr
/modele_modele_h_sin_frequence.txt :
changement de la bibliothèque utilisée
(libhbound_demonstrateur_frequence.so) et ajout de la fréquence en
argument deH_BOUNDARY_FOR_SOLID_PROG.
revenir au niveau du dossier TP6
cd ../..
TP6 - Partie 3 : Hack du solveur : puissance volumique donnée par
une espérance [autre chose que de la thermique]
On va maintenant présenter des hacks. Dans cette Partie 3, il s'agit d'un
exercice académique. Dans la Partie 4 suivante, un deuxième exemple sera
décrit qui a finalement été intégré dans le stardis officiel.
Donner une explication "large" du besoin de coupler la thermique à
différentes physiques (chimie, électricité, etc). On peut alors hacker
stardis pour prendre en compte cette nouvelle physique, qu'on suppose décrite
par l'espérance d'une variable aléatoire.
Ici on prend un exemple où c'est la puissance volumique qui est décrite comme
l'espérance d'une variable aléatoire. Plutôt que de choisir un modèle
physique, on prend le cas caricatural d'une puissance volumique donnée par
une gaussienne.
Intention en trois étapes :
Partie 3.1 : installer son propre projet dérivé de stardis
Partie 3.2 : changer une fonction dans le solveur
Partie 3.3 : ajouter un nouveau paramètre dans la description du système
physique lue par stardis
cp -r ${DEMONSTRATEUR_2}/TP6/src/hack_puissance_volumique .
cd hack_puissance_volumique
Partie 3.1 : installation du contexte pour hacker
On commence par expliciter les gestes pour l'installation.
On présente rapidement star-build (juste le concept de gestionnaire de paquet
pour que les versions des paquets installés soient cohérents avec la version
de stardis installée par exemple).
git clone https://gitlab.com/meso-star/star-build.git -b 0.0
cd star-build/
installer stardis et ses dépendances :
make clean
rm -fr cache local
make BUILD=src/stardis_0.11.1.sh \
REPO_BIN_ONLINE=https://www.meso-star.com/packages/v0.4 \
DISTRIB_PARALLELISM=None
On va maintenant utiliser ce stardis plutôt que celui installé chez lafrier :
. ./local/etc/stardis.profile
On va repartir des sources qui ont été installées dans cache/stardis-solver.
On copie ce dossier et on va le modifier plus tard :
cp -r cache/stardis-solver/0.16.1/ ../stardis-solver-0.16.1
On nettoie les fichiers temporaires qui ont été générés :
cd ../stardis-solver-0.16.1
make distclean
ls
On commence donc par vérifier qu'on est en capacité de le modifier puis faire
tourner ce code là. Pour cela, on vous propose d'écrire "Hello World" dans la
console et de retourner une erreur pour arrêter le programme :
vim src/sdis_solve_probe_Xd.h
Dans la fonction XD(solve_probe), ajoutez les lignes suivantes :
XD(solve_probe)(...)
{
...
ATOMIC res = RES_OK;
log_err(scn->dev, "Hello World !\n");
goto error;
...
}
On souhaite écraser la bibliothèque 'stardis-solver' installée dans le dossier
'star-build/local' par la version que nous venons de modifier dans le dossier
'stardis-solver-0.16.1'. Pour cela, on édite le fichier config.mk :
vim config.mk
Remplacer le chemin d'installation PREFIX par le chemin absolu vers le dossier
star-build/local. On s'attend à un chemin de la forme :
PREFIX=/home/etudiant/nom/TP6/hack_puissance_volumique/star-build/local
Changer le DISTRIB_PARALLELISM en remplaçant la ligne par:
DISTRIB_PARALLELISM = None
Installer stardis-solver dans le dossier spécifié :
make install
On exécute maintenant stardis :
cd ../cube
stardis -M model.txt -p 0.5,0.5,0.5
Vous devez constater qu'il y a bien 'Hello world' écrit dans votre console.
BRAVO ! Vous êtes maintenant prêt à développer vos propres fonctionnalités !
Avant de continuer, commentez la ligne goto error; pour éviter que le
programme ne s'arrête :
cd ../stardis-solver-0.16.1
vim src/sdis_solve_probe_Xd.h
NOTE : pour l'exercice suivant, le git diff ainsi que les fichiers modifiés
sont stockés (au cas-où) dans le dossier
${DEMONSTRATEUR_2}/TP6/src/code_hack_puissance_volumique.
Partie 3.2 : puissance volumique donnée comme une espérance
Vous allez d'abord modifier le calcul de la puissance volumique.
On fait le choix de modifier l'algorithme du WOS car le code est le plus
lisible, donc du fichier src/sdis_heat_path_conductive_wos_Xd.h :
vim src/sdis_heat_path_conductive_wos_Xd.h
Recherchez power dans le fichier. Vous identifiez que la fonction
handle_volumic_power_wos est dédiée à la gestion de la puissance volumique,
et qu'elle est appelée par la fonction XD(conductive_path_wos).
Vous voyez (ligne 210) que la température accumulée est
T->value += props->power * term;
Ici, il s'agira de ne plus utiliser props->power de façon déterministe mais
une réalisation de la variable aléatoire de loi normale.
Dupliquez la fonction handle_volumic_power_wos pour créer votre nouvelle
fonction handle_gaussian_volumic_power_wos. Définissez et initialisez une
nouvelle variable power de type double :
double power = 0;
La puissance volumique est cette fois obtenue en échantillonnant la
distribution normale autour de props->power, avec un écart-type choisi
arbitrairement. Pour cela, il existe déjà la fonction ssp_ran_gaussian dans
la bibliothèque ssp. Sa définition est donnée dans le fichier d'API
star-build/local/include/star/ssp.h.
vim ../star-build/local/include/star/ssp.h
vim src/sdis_heat_path_conductive_wos_Xd.h
Vous pouvez donc écrire :
power = ssp_ran_gaussian(rng, props->power, 100000);
T->value += power * term;
Vous voyez qu'il faut un générateur aléatoire rng comme premier argument de
cette fonction. La fonction handle_volumic_power_wos ne dispose pas de
telle variable, par contre c'est le cas de la fonction appelante
XD(conductive_path_wos). Vous devez donc modifier les arguments de votre
nouvelle fonction pour y ajouter struct ssp_rng* rng.
La fonction est bien définie mais n'est pas appelée, vous allez donc
maintenant modifier la fonction XD(conductive_path_wos). Afin de pouvoir
appeler votre version modifiée de stardis ou alternativement le calcul
originel, vous utiliserez une macro pré-processeur.
Ajoutez les lignes suivantes :
/* Add the volumic power density */
res = XD(handle_gaussian_volumic_power_wos)(scn, &props, rng, dst, &power_term, T);
res = XD(handle_volumic_power_wos)(scn, &props, dst, &power_term, T);
if(res != RES_OK) goto error;
make install
On va tester sur la scène du cube du starter_pack :
cd ../cube
stardis -V 3 -M model.txt -p 0.5,0.5,0.5 -n 10000 -e -a wos
Analyse physique :
Dans un nouveau terminal, sourcez stardis "normal" et exécutez le script
suivant qui estime la température à différents point dans le cube solide.
Ou alternativement commentez la ligne :
et recompilez avant d'exécuter :
./run_stardis_several_positions.sh data_stardis.txt
Faite de même dans le terminal qui a sourcé la version hackée de stardis
avec une puissance volumique qui est échantillonnée
./run_stardis_several_positions.sh data_hacked_stardis.txt
Comparez les deux :
vous pouvez lire les fichiers data_stardis.txt et data_hacked_stardis.txt ou
bien lancer le plot suivant :
{
echo "plot 'data_stardis.txt' u 1:2:3 w yerrorbar title" \
"'constant vol. power', 'data_hacked_stardis.txt'" \
"u 1:2:3 w yerrorbar title 'sampled vol. power'"
echo "pause -1"
} > plot.gp
gnuplot plot.gp
L'estimation de la température dans la tranche est donc très peu impactée par
le fait que la puissance volumique soit elle-même échantillonnée.
C'est une bonne nouvelle !
Si vous le souhaitez vous pouvez faire le test avec différentes valeurs
d'écart-type pour la gaussienne.
TODO
Eventuellement un commentaire physique sur le profil quadratique de la
température dans la tranche.
Partie 3.3 : paramètres contrôlés par l'utilisateur
Maintenant, on souhaite que le paramètre d'écart-type de la loi normale soit
donné comme un paramètre dans le fichier d'entrée de Stardis.
ATTENTION, comme décrit dans le paragraphe de la fin, on voit que c'est plus
long...
De la même manière qu'il y a props->power, on voudrait maintenant un champ
props->power_std pour l'écart-type. Identifier dans le code le type de la
variable props ('const struct solid_props* props'). Recherchez où cette
structure est définie pour la modifier ensuite :
cd ../stardis-solver-0.16.1/
grep "struct solid_props {" src/*
Editez donc la structure pour ajouter un champ
double power_std; /* Ecart-type de la puissance volumique */
juste après la déclaration de power. A la ligne juste en dessous, modifiez
l'initalisateur par défaut pour initialiser ce nouveau champ par exemple à 0.
vim src/sdis_medium_c.h
Vous devez avoir :
struct solid_props {
...
double power; /* Volumic power /
double power_std_dev; / Ecart-type de la puissance volumique */
...
}
En cherchant les appels à power, vous voyez que ce champ est rempli par la
fonction solid_get_properties. Modifiez là pour tenir compte de l'écart-type
sur la puissance volumique. Vous devriez avoir :
static INLINE res_T
solid_get_properties
(const struct sdis_medium* mdm,
const struct sdis_rwalk_vertex* vtx,
struct solid_props* props)
{
...
props->power = solid_get_volumic_power(mdm, vtx);
props->power_std_dev = solid_get_volumic_power_std(mdm, vtx);
...
}
Il faut alors définir une nouvelle fonction :
static INLINE double
solid_get_volumic_power_std
(const struct sdis_medium* mdm,
const struct sdis_rwalk_vertex* vtx)
{
ASSERT(mdm && mdm->type == SDIS_SOLID);
return mdm->shader.solid.volumic_power_std_dev
? mdm->shader.solid.volumic_power_std_dev(vtx, mdm->data)
: SDIS_VOLUMIC_POWER_NONE;
}
Faite appel à ce nouveau champ lors du tirage de la puissance volumique :
vim src/sdis_heat_path_conductive_wos_Xd.h
Vous devez donc avoir remplacé
power = ssp_ran_gaussian(rng, props->power, 100000);
par
power = ssp_ran_gaussian(rng, props->power, props->power_std_dev);
make install
On obtient une erreur :
erreur: « const struct sdis_solid_shader » n'a pas de membre nommé
« volumic_power_std_dev »
grep "struct sdis_solid_shader {" src/*
on voit que cette structure est définie dans
src/sdis.h
TODO
Mettre une définition pour l'API sdis et le fait que c'est cette interface
qui définit le point d'entrée vers le solveur.
En fait, depuis stardis, le seul moyen d'accéder à cette valeur est de
passer par les structures définies dans l'API "dis.h" :
vim src/sdis.h
Recherchez les occurences de volumic_power, vous voyez que ce champ apparaît
dans struct sdis_solid_shader. Ajoutez un nouveau champ
volumic_power_std_dev dans la structure, en copiant ce qui est fait pour
volumic_power. Vous devriez avoir :
struct sdis_solid_shader {
...
sdis_medium_getter_T volumic_power; /* In W.m^-3 /
sdis_medium_getter_T volumic_power_std_dev; / In W.m^-3 */
...
}
Ici il faut aussi mettre à jour l'initialisateur par défaut.
A remplacer par la ligne suivante, où la fonction définissant l'écart-type
sera initialisé à NULL :
make install
Le solveur est prêt pour recevoir ce nouveau paramètre, maintenant vous allez
modifier stardis :
cd ..
cp -r star-build/cache/stardis/0.11.1/ stardis-0.11.1/
cd stardis-0.11.1/
make distclean
vim config.mk
Comme dans la Partie 3.1, il vous faut spécifier PREFIX vers le dossier
star-build/local et changer le DISTRIB_PARALLELISM en remplaçant la ligne par:
DISTRIB_PARALLELISM = None
make install
Dans le fichier décrivant le système, on souhaite maintenant modifier la
grammaire associée au mot clé "SOLID" pour ajouter le paramètre
volumic_power_std_dev après volumic_power :
SOLID name lambda rho cp delta initial-temp imposed-temp
volumic-power side-specifier slt_file
devient
SOLID name lambda rho cp delta initial-temp imposed-temp
volumic-power volumic-power-std-dev side-specifier slt_file
Pour cela, vous devez modifier le parsing, c'est-à-dire la lecture et le
traitement de ces données :
vim src/stardis-parsing.c
Dans la fonction process_solid :
if(solid->vpower != 0 && stardis->picard_order > 1) {
...
}
CHK_ARG(idx, "volumic power std");
res = cstr_to_double(arg, &solid->vpower_std_dev); /* seule ligne à
ajouter /
logger_print(stardis->logger, LOG_ERROR, "Std lue : %f\n",
solid->vpower_std_dev); / juste pour vérifier que cette
fonction est lue */
/* Actual solid creation is defered until geometry is read to allow
* enclosure shape VS delta analysis (and auto delta computation) */
Exercice : rajoutez ce nouveau champ à la structure struct solid
Solution :
grep "struct solid {" src/*
vim src/stardis-solid.h
Vous devriez avoir :
struct solid {
...
double vpower;
double vpower_std_dev;
...
}
Compiler et il faut maintenant initialiser ce champ de la structure :
vim src/stardis-solid.c
Dans la fonction init_solid, ajoutez la ligne :
(*dst)->vpower_std_dev = 0;
La fonction create_solver_solid établit un lien entre les structures de
stardis et celle du solver.
Exercice : a partir de l'exemple de la puissance volumique, établissez le lien
entre l'écart-type lu par stardis et celui qui sera utilisé par le solveur
Solution :
Vous devriez avoir :
res_T
create_solver_solid
(struct stardis* stardis,
const struct solid* solid_props)
{
...
if(solid_props->vpower != 0) solid_shader.volumic_power = solid_get_power;
if(solid_props->vpower != 0) solid_shader.volumic_power_std_dev = solid_get_power_std_dev;
if(solid_props->solid_id >= darray_media_ptr_size_get(&stardis->media)) {
...
}
Ainsi que la fonction suivante, inspirée de solid_get_power :
static double
solid_get_power_std_dev
(const struct sdis_rwalk_vertex* vtx,
struct sdis_data* data)
{
const struct solid* const* solid_props = sdis_data_cget(data);
(void)vtx;
return (*solid_props)->vpower_std_dev;
}
make install
cd ../cube
stardis -V 3 -M model_std_dev.txt -p 0.5,0.5,0.5 -n 10000 -e -a wos
A l'issue de cet exercice, on voit donc que la modification dans le solveur
est assez directe, mais ça se complique grandement quand on doit cette fois
modifier stardis. "Et c'est normal." Une option peut être de ne pas passer
par stardis mais par un détournement des tests de non régression.
Ces tests servent à vérifier que le résultat de stardis est conforme à la
solution analytique sur certains cas. Ce découpage stardis / solveur a même
permis d'aller encore plus loin en intégrant le solveur à Syrthes, qui
possédait déjà un solveur maillé. Cela permet de faire tourner les deux
codes sur un même système (même CAO).
TODO
Une vidéo d'Isabelle pour parler du papier d'EDF sur la comparaison entre
les deux méthodes (MC / maillée).
TP6 - Partie 4 : des hacks plus compliqués ; exemple du flux solaire dans
l'habitat
Objectif : bénéficier de l'infrastructure solide de stardis pour y développer
une nouvelle fonctionnalité très spécifique, sans subir tout le poids de la
structure, c'est-à-dire qu'on ne se soucie pas de casser d'autres
fonctionnalités qu'on n'utilise pas.
C'est faisble et on présente ici un exemple issu du projet ANR MC2,
basé sur la présentation de Vincent F. aux journées Consortium.
nastar:/nastar/mesostar/git/stardis-journees-consortium-2024.git
- le contexte du projet MC2, papier de Cyril
- les features ajoutées
- 4 développeurs
- Peu de lignes de codes modifiées finalement !
Elles sont très localisées, rincipalement dans le solveur.
Quelques nouveaux fichiers pour les nouvelles fonctionnalités :
sdis_solar et sdis_spa
Ce hack a si bien fonctionné, que les features ont été redéveloppées dans
la version officielle de stardis. Les propriétés programmables sont aussi
au coeur de la proposition, pour avoir des propriétés variables issues de
simulations climatiques par exemple. Cette partie reste à la charge du
physicien développeur, de façon indépendante de Stardis comme on l'a vu dans
l'exercice 2.
Mettre l'image de la ville avec des "ombres solaires".
TODO
Une vidéo de Cyril qui nous raconte le projet MC2.