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 :

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 :

Les accumulateurs sont d'abord vidés.
Pour chaque réalisation (FOR_EACH) :

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 :

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 :

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,

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 :

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

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 :

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 :

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

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.