Informations

Projet 				: 	EPFL  Notebooks de démonstrations
Auteur		 		: 	Amina Matt
Date de création 		:	Mars 2019
But					: 	Illustration de la structure des matériaux  (Indices de Miller, plans dense, empilement compact)
Historique des révisions	:

Comment utiliser le Notebook?

Mac Os:  Pour évaluer toutes les cellules du notebook utiliser ⌘+A et  ⇧+↵ . Pour fermer la fenêtre de visualisation utiliser ⌘+W.

Windows:  Pour évaluer toutes les cellules du notebook utiliser Ctrl+A et  ⇧+↵ . Pour fermer la fenêtre de visualisation utiliser Alt+F4.

Pour voir le code utilisé double-cliquer sur le symbole  ou correspondant à la section souhaitée. Pour la refermer double cliquer sur   correspondant.

Pour en savoir plus sur la méthode de simulation utilisée utiliser les liens.

Structure des matériaux: Systèmes cubiques and plans cristallographiques

Pour évaluer toutes les cellules du Notebook utiliser ⌘+A et  ⇧+↵ . Pour fermer la fenêtre de visualisation utiliser ⌘+W.

Fonctions

Structure cristalline

Give the primitive basis of the Bravais lattice

structureOnly[bravais_]:=LatticeData[bravais,"Basis"]//Normal

(*e.g.*)structureOnly["SimpleCubic"]

Give the atom positions, the drawing of the cell axes and the basis vector.

structure[bravais_, size_, radius_] :=
structure[bravais, size, radius]=
 Module[{basis, coordinates, atomes, unitCellAxes, boxSize, cubicBasis},
  basis = structureOnly[bravais];(*get the basis vectors*)
  unitCellAxes = Arrow[{{0, 0, 0}, #}] & /@ basis;(*draw a unit cell with the basis vectors*)
  coordinates = Flatten[Table[i basis[[1]] + j basis[[2]] + k basis[[3]], {i, 0, size}, {j, 0, size}, {k, 0, size}], 2]; (*Create the atoms of the cristal structure*)
  
  (*As LatticeData contains the primitive vectors we need a trick to use the conventionnal ones*)
  If[bravais == "FaceCenteredCubic" || bravais == "BodyCenteredCubic",
   cubicBasis = {{2, 0, 0}, {0, 2, 0}, {0, 0, 2}}; boxSize = size + 7;
   unitCellAxes = Arrow[{{0, 0, 0}, #}] & /@ cubicBasis;
   coordinates = Flatten[Table[i basis[[1]] + j basis[[2]] + k basis[[3]], {i, -boxSize, boxSize}, {j, -boxSize, boxSize}, {k, -boxSize, boxSize}], 2];
   basis = cubicBasis;
   boxSize = size;
   coordinates = Select[coordinates, RegionMember[Cuboid[{-0, -0, -0}, {2*boxSize, 2* boxSize, 2*boxSize}], #] &], boxSize = size,
   atomes = Map[Ball[#, radius*unitCellAxes[[1,1,2,1]]] &, coordinates]];
  atomes = Map[Ball[#, radius*unitCellAxes[[1,1,2,1]]] &, coordinates];
  
  {atomes, unitCellAxes, basis}
  ]

(*e.g.*)structure["SimpleCubic",1,0.5][[1;;2]]

Graphics3D[{Opacity[0.5],%}]

The structures are precomputed to avoid lagging in the visualization

preComputedStructures=Table[structure[#,1,i]&/@{"SimpleCubic","BodyCenteredCubic","FaceCenteredCubic"},{i,{
0.125,0.25,Sqrt[2]/4 ,Sqrt[3]/4,0.5}}];

Indices de Miller

divideBy0[h_]:=1/h (*Miller indices are defined as 1/h *)

divideBy0[0]=0; (*This trick is used to avoid the indetermination*)

The following function draws a plane based on the miller indices

millerindicesFunction[h_,k_,l_,basis_]:=
millerindicesfunction[h,k,l,basis](*this trick is used to store values and make the visualisation faster*)=
Module[{},
(*If one miller indice is zero, then we need a plane parallel to an axe*)
If[h==0,inf=InfinitePlane[(*p*)divideBy0[k]*basis[[2]],{(*v2*)divideBy0[k]*basis[[2]]-divideBy0[l]*basis[[3]],(*v1*){1,0,0}}],Nothing];(*The plane is defined with one point and two vectors*)
If[k==0,inf=InfinitePlane[(*p*)divideBy0[l]*basis[[3]],{(*v2*)divideBy0[h]*basis[[1]]-divideBy0[l]*basis[[3]],(*v1*){0,1,0}}],Nothing];
If[l==0,inf=InfinitePlane[(*p*)divideBy0[k]*basis[[2]],{(*v2*)divideBy0[k]*basis[[2]]-divideBy0[h]*basis[[1]],(*v1*){0,0,1}}],Nothing];
(*If two miller indices are zero, then we need a plane parallel to two axes*)
If[h==0 && k==0,inf=InfinitePlane[(*p*)divideBy0[k]*basis[[3]],{(*v2*){0,1,0},(*v1*){1,0,0}}],Nothing];(*The plane is defined with one point and two vectors*)
If[k==0 && l==0,inf=InfinitePlane[(*p*)divideBy0[l]*basis[[1]],{(*v2*){0,1,0},(*v1*){0,0,1}}],Nothing];
If[l==0 && h==0,inf=InfinitePlane[(*p*)divideBy0[k]*basis[[2]],{(*v2*){1,0,0},(*v1*){0,0,1}}],Nothing];
If[h≠0 &&k≠0 && l≠0,inf=InfinitePlane[{divideBy0[h]*basis[[1]],divideBy0[k]*basis[[2]],divideBy0[l]*basis[[3]]}],Nothing];
inf]

The following function moves the plane in the cristal

move[plane_,vector_]:=If[Dimensions[plane][[1]]==1 (*we need to differentiate the case where the plane is expressed from three points (dim==1) and when it is expressed from one point and two vectors (dim==2)*),
InfinitePlane[plane[[1]]+{vector,vector,vector}],
If[Total@plane[[1]]==2(* two 1 and one 0*),
InfinitePlane[plane[[1]]+vector,plane[[2]]],
InfinitePlane[plane[[1]]+{Total@vector,Total@vector,Total@vector},plane[[2]]]]
]

(*e.g.*)
basis=structureOnly["SimpleCubic"];

Table[millerindicesFunction[h,k,l,structureOnly[basis]],{h,{0,1,2}},{k,{0,1,2}},{l,{0,1,2}},{basis,{"SimpleCubic","BodyCenteredCubic","FaceCenteredCubic"}}];

Sélection des points appartenant à la maille

The following function selects the point that belong to the selected plane

selectionMiller[allAtomes_,plane_]:=selectionMiller[allAtomes,plane]=
Module[{allCoordinates,allDistances,atomesOfInterestIndices,atomesOfInterest},
allCoordinates=allAtomes[[All,1]];
allDistances=RegionDistance[plane,#]&/@allCoordinates;
atomesOfInterestIndices=Position[N@#&/@allDistances,0.];
atomesOfInterest=allAtomes[[#]]&/@atomesOfInterestIndices;
atomesOfInterest
]

Démonstration 1 : Système cubique et modèle des sphères rigides

cubicSystems=
Manipulate[
DynamicModule[{plane,atomes,unitCellAxes,planeOfInterest,basis,cube,atomesOfInterest,s=1,atomesGraphics,unitCellGraphics,unitCubeGraphics,background}(*local variables*),
(*---Calculation---*)
{atomes,unitCellAxes,basis}=structure[bravais,s,radius];(*Obtain the atomes coordinates, the unit cell axes and the vector basis *)
a=unitCellAxes[[1,1,2,1]];
cube=Graphics3D[{Blue,Opacity[0.4],Cuboid[{0,0,0},{a,a,a}]}];
background=Graphics3D[{Transparent,EdgeForm[],Cuboid[{0,0,0},{a,a,a}]}];(*This is a transparent cube used as a background to avoid change in the imagesize*)
(*---Graphics---*)
atomesGraphics=Graphics3D[{LightBlue,atomes},ImageMargins->{{15,15},{15,15}},If[cutFlag,PlotRange->{{0,a},{0,a},{0,a}},PlotRange->All],Boxed->False,ImageSize->Large ,Axes->True,Ticks->None,AxesLabel->{"x","y","z"},LabelStyle->{16,Bold}];
unitCellGraphics=Graphics3D[{Black,unitCellAxes}];
unitCubeGraphics=If[cubicFlag,cube,background];
(*---Visualisation---*)
Show[atomesGraphics,unitCellGraphics,unitCubeGraphics]],(*Depending on the control values different things are shown*)
(*---Controls---*)
Delimiter,
Style["Systèmes cristallins cubiques",Bold],
Style["Sélectionne un système cristallin pour visualiser l'arrangement des atomes correspondant."],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
{{bravais,"SimpleCubic",Style["Bravais",16]},{"SimpleCubic"-> "Cubique Simple","BodyCenteredCubic"-> "Cubique Centre","FaceCenteredCubic"-> "Cubique à Face Centrées"}},
{{cubicFlag,True,"Cube unitaire"},{True,False}},
Delimiter,
Style["La maille est l'unité de répétition périodique d'un système cristallin."],
Style["Utilise le bouton suivant pour visualiser uniquement les atomes appartenant à la maille."],
{{cutFlag,False,"Maille."},{True,False}},
(*--question 1--*)
Style["Question",Bold],
Style["Que peux-tu déduire sur la proportion d'atomes sur les faces, les coins et l'intérieur du cube unitaire?"],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
{{answerFlag,False,"Réponse"},{True,False}},
Dynamic[If[answerFlag,Style["Sur les faces seulement ((1)/2) de l'atome appartient à la maille. \nSur les coins seuleument (1/(8 )) de l'atome appartient à la maille.\nAu centre, l'entier de l'atome est dans la maille."](*--- ←MODIFY THE ANSWER ---*),Style[""]]],
(*---*)
Delimiter,
Style["Le modèle des sphères rigides décrit l'arrangement des atomes d'un cristal comme l'empilement de sphères rigides, i.e. pas d'intersection."],
{{radius,0.125,Style["Rayon de sphères",16]},{0.125-> "(1/8) a",0.25-> "(1/4) a",Sqrt[2]/4->"((Sqrt[2])/4)a",Sqrt[3]/4->"((Sqrt[3])/4)a",0.5 -> "(1/2) a"}},
Style["Commentaire: le paramètre de maille vaut a." ],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
(*--question 2--*)
Style["Question",Bold],
Style["Peux-tu déduire sur la valeur du rayon selon le modèle des sphères rigides pour chaque modèle?"],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
{{answerFlag2,False,"Réponse"},{True,False}},
Dynamic[If[answerFlag2,Style["Pour le réseau Cubique Simple, le rayon vaut (1/2)a.\nPour le réseau Cubique Centré, le rayon vaut ((Sqrt[3])/4)a.\nPour le réseau Cubique à Faces Centrées, le rayon vaut ((Sqrt[2])/4)a."](*--- ←MODIFY THE ANSWER ---*),Style[""]]],
Delimiter,LabelStyle->16,ControlPlacement->Left
];

(*CreateDocument[cubicSystems,WindowSize->All]*)

Démonstration 2 : Plans cristallographiques

planeDensities=
DynamicModule[{plane,atomes,unitCellAxes,planeOfInterest,basis,atomesOfInterest,a,
vp=ViewPoint/.Options[Graphics3D],
vv=ViewVertical/.Options[Graphics3D]
},
Manipulate[
(*Calculation*)
{atomes,unitCellAxes,basis}=structure[bravais,s,radius];
a=unitCellAxes[[1,1,2,1]];
(*Call function structure and obtain the atomes coordinates, the unit cell axes and the vector basis *)
plane=millerindicesFunction[h,k,l,basis];(*Call function millerIndices to obtain the plane drawing *)
vector=x*a*Normalize[{h,k,l}];(*Miller direction definition*)
atomesOfInterest=selectionMiller[atomes,plane];(*Call function to select atomes belonging to the plane*)
(*Visualisation*)
Grid[{{
(*Full*)
Graphics3D[
{
{Opacity[opacityValue],atomes},{Black,Thickness[0.008],unitCellAxes},{Blue,move[plane,vector]},{Thickness[0.018],Red,Arrow[Tube[{{0,0,0},4{a*hh,a*kk,a*ll}},Scaled[0.005]]]}
},ImageSize->Medium,Boxed->False,If[axesFlag,{Axes->True,AxesEdge->{{-1,-1},{-1,-1},{-1,-1}},Ticks->None,AxesLabel->{"x","y","z"}},Nothing], LabelStyle->{16,Bold},ViewProjection-> "Orthographic",ViewPoint->Dynamic[vp],ViewVertical->Dynamic[vv]],
Graphics3D[
{
{Opacity[opacityValue],atomesOfInterest},{Blue,plane},{Black,unitCellAxes},{Thickness[0.01],Red,Arrow[Tube[{{0,0,0},{a*hh,a*kk,a*ll}},Scaled[0.005]]]}
}
,ImageSize->400,Boxed->False,ViewProjection-> "Orthographic",ViewPoint->Dynamic[vp],ViewVertical->Dynamic[vv]]
}}],
(*Controls*)
Delimiter,
Style["Paramètres du système cristallin"],
{{bravais,"SimpleCubic",Style["Bravais",16]},{"SimpleCubic"-> "Cubique Simple","BodyCenteredCubic"-> "Cubique Centré","FaceCenteredCubic"-> "Cubique à Face Centrées"}},
{{s,3,Style["Taille du système size",14]},{1,2,3}},
{{radius,0.5,Style["Rayon de sphères",14]},{Sqrt[2]/4 ->"((Sqrt[2])/4)a",Sqrt[3]/4->"((Sqrt[3])/4)a",0.5 -> "(1/2) a"}},
{{x,0.0,"Position du plan"},0.0,1},
Delimiter,
Dynamic[StringJoin["Indices du Plan de Miller : (",ToString@h,ToString@k,ToString@l,")"]],{{h,1,Style["h",14]},{0,1,2}},{{k,1,Style[" k",14]},{0,1,2}},
{{l,1,Style[" l",14]},{0,1,2}},Delimiter,
Dynamic[StringJoin["Indices de la Direction de Miller : [",ToString@hh,ToString@kk,ToString@ll,"]"]],
{{hh,1,Style["h",14]},{0,1,2}},
{{kk,1,Style[" k",14]},{0,1,2}},
{{ll,1,Style[" l",14]},{0,1,2}},Delimiter,
Style["Apparence"],
{{axesFlag,True,"Axes"},{True,False}},
{{opacityValue,1,"Opacity"},0,1},
(*--Question 1--*)
Style["Questions",Bold],
Style["Quelle relation existe-t-il entre les droites et les plans de mêmes indices (dans ces systèmes cubiques)?"],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
{{answerFlag,False,"Réponse"},{True,False}},
Dynamic[If[answerFlag,Style["Les droites sont perpendiculaires aux plans de mêmes indices."](*--- ←MODIFY THE ANSWER ---*),Style[""]]],
(*---*)
(*--Question 2--*)
Style["Quelles sont les indices de Miller des plans denses pour chaque système?"],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
{{answerFlag2,False,"Réponse"},{True,False}},
Dynamic[If[answerFlag2,Style["Pour le réseau Cubique Simple, les plans denses sont <100>.\nPour le réseau Cubique Centré, les plans denses sont <110>.\nPour le réseau Cubique à Faces Centrées, les plans denses sont <111>."](*--- ←MODIFY THE ANSWER ---*),Style[""]]]
(*---*)
,LabelStyle->16]];
(*CreateDocument[planeDensities,WindowSize->All]*)

Démonstration 3 : Empilement compact

First common layer

basisStacking=LatticeData["HexagonalClosePacking","MinimalVectors"]//Normal; (*Vectors for the hexagonal close packing *)
size=3;
atomesTMP=Catenate[{{{0,0,0}},Flatten[Table[i basisStacking[[1]]+j basisStacking[[2]]+k basisStacking[[3]],{i,-0,size},{j,-0,size},{k,-0,size}],2]}]; (*Create the cristal structure*)

firstLayer=Select[atomesTMP,#[[3]]==0&];(*Only the atoms inplane*)
firstLayerGraphics=Graphics3D[{Blue,Sphere[#,0.5]&/@firstLayer},ViewPoint->Top,ViewProjection->"Orthographic"];

Second layer

vectorB={0.5,Sqrt[3]/6,0.5}; (*Displacement of second layer respect to first layer*)
layerB=#+vectorB&/@firstLayer;
layerBGraphics=Graphics3D[{Red,Sphere[#,0.5]&/@layerB},ViewPoint->Top,ViewProjection->"Orthographic"];

Third layer

vectorhcp={0.5,Sqrt[3]/6,0.5};
vectorcfc={-0.5,-Sqrt[3]/6,0.5};
hcpThirdlayer=#+vectorhcp&/@layerB;
hcpThirdlayerGraphics=Graphics3D[{Green,Sphere[#,0.5]&/@hcpThirdlayer},ViewPoint->Top];

cfcThirdlayer=#+vectorcfc&/@layerB;

cfcThirdlayerGraphics=Graphics3D[{Blue,Sphere[#,0.5]&/@cfcThirdlayer},ViewPoint->Top];

Altogether

closePacking=
Manipulate[
Module[{basisStacking,size,atomesTMP,firstLayerGraphics,background,layerBGraphics,hcpThirdlayerGraphics,cfcThirdlayerGraphics},
(*Calculation*)
firstLayerGraphics=Graphics3D[{Blue,Sphere[#,0.5]&/@firstLayer},ViewPoint->viewpoint,ImageSize-> Medium,ImageMargins->{{50,50},{50,50}},ViewProjection->"Orthographic",Boxed->False];
layerBGraphics=Graphics3D[{Red,Sphere[#,0.5]&/@layerB},ViewPoint->viewpoint,ViewProjection->"Orthographic"];

hcpThirdlayerGraphics=Graphics3D[{Green,Sphere[#,0.5]&/@hcpThirdlayer},ViewPoint->viewpoint];

cfcThirdlayerGraphics=Graphics3D[{Blue,Sphere[#,0.5]&/@cfcThirdlayer},ViewPoint->viewpoint];
background=Graphics3D[{Transparent,EdgeForm[],Cuboid[]}, ViewPoint->Front,Boxed->False];
(*Visualisation*)
Grid[{{Style["HCP Hexagonal compact",20,Bold],Style["CFC Cubique faces centrées",20,Bold]},
{
Show[If[firstLayerFlag,firstLayerGraphics/.viewpoint-> Front,background],If[secondLayerFlag,layerBGraphics/.viewpoint-> Front,background],If[thirdLayerFlag,cfcThirdlayerGraphics/.viewpoint-> Front,background]],
Show[If[firstLayerFlag,firstLayerGraphics/.viewpoint-> Front,background],If[secondLayerFlag,layerBGraphics/.viewpoint-> Front,background],If[thirdLayerFlag,hcpThirdlayerGraphics/.viewpoint-> Front,background]]
},
{
Show[If[firstLayerFlag,firstLayerGraphics/.viewpoint-> Top,background],If[secondLayerFlag,layerBGraphics/.viewpoint-> Top,background],If[thirdLayerFlag,cfcThirdlayerGraphics/.viewpoint-> Top,background]],
Show[If[firstLayerFlag,firstLayerGraphics/.viewpoint-> Top,background],If[secondLayerFlag,layerBGraphics/.viewpoint-> Top,background],If[thirdLayerFlag,hcpThirdlayerGraphics/.viewpoint-> Top,background]]
}}]],
(*Controls*)
Style["Empilement",20,Bold],
{{firstLayerFlag,True,"Premier plan"},{True,False}},
{{secondLayerFlag,False,"Deuxième plan"},{True,False}},
{{thirdLayerFlag,False,"Troisième plan"},{True,False}},
(*--Question 1--*)
Style["Question",Bold],
Style["Quelle est la différence dans l'empilement HC et l'empilement CFC?"],(*--- ←ADD EXPLANATION OR INSTRUCTION---*)
{{answerFlag,False,"Réponse"},{True,False}},
Dynamic[If[answerFlag,Style["L'hexagonal compact est de type ABABAB tandis que le cubique face centrée est de type ABCABC"](*--- ←MODIFY THE ANSWER ---*),Style[""]]]
(*---*)
,LabelStyle->16
];

(*CreateDocument[closePacking,WindowSize->All]*)

Exercice 1 : Indices de droites et plans de Miller

exercise1=Manipulate[
DynamicModule[{bravais="SimpleCubic",s=1,radius=0.5,a=1(*plane,atomes,unitCellAxes,planeOfInterest,basis,atomesOfInterest*)},
(*Calculation*)
{atomes,unitCellAxes,basis}=structure[bravais,s,radius];(*Obtain the atomes coordinates, the unit cell axes and the vector basis *)
plane=millerindicesFunction[h,k,l,basis];(*Call function millerIndices to obtain the plane drawing *)
vector=a*Normalize[{h,k,l}];(*Miller direction definition*)
atomesOfInterest=selectionMiller[atomes,plane];(*Call function to select atomes belonging to the plane*)
(*Visualisation*)
Grid[{{
Show[Graphics3D[{Black,Thickness[0.008],unitCellAxes},AxesEdge->{{-1,-1}, {-1,-1}, {-1,-1}},Axes-> True,Ticks->None, AxesLabel->{"x","y","z"},LabelStyle->{16,Bold},If[cubeFlag,Boxed-> True, Boxed-> False],ImageSize->Large],Graphics3D[{Blue,plane}],Graphics3D[{Thickness[0.018],Blue,Arrow[{{0,0,0},{a*hh,a*kk,a*ll}}]}],ViewProjection-> "Orthographic"]
}}]],
(*Controls*)
Style["Exercice sur les indices de Miller",Bold],
(*----ADD EXPLANATION OR INSTRUCTION---*)
(*Style["add comment here"],*)
(*----*)
Delimiter,
Style["Dessine les plans en fonction de leurs indices de Miller et vérifie en utilisant la visualisation."],
Dynamic[StringJoin["Indices du Plan de Miller : (",ToString@h,ToString@k,ToString@l,")"]],
{{h,1,Style["h",14]},{-2,-1,0,1,2}},
{{k,1,Style[" k",14]},{-2,-1,0,1,2}},
{{l,1,Style[" l",14]},{-2,-1,0,1,2}},
Delimiter,
Dynamic[StringJoin["Indices de la Direction de Miller : [",ToString@hh,ToString@kk,ToString@ll,"]"]],
{{hh,1,Style["h",14]},{-2,-1,0,1,2}},
{{kk,1,Style[" k",14]},{-2,-1,0,1,2}},
{{ll,1,Style[" l",14]},{-2,-1,0,1,2}},Delimiter,
Style["Apparence"],
{{cubeFlag,True,"Cube"},{True,False}},LabelStyle->16];

(*CreateDocument[exercise1,WindowSize->All]*)

Visualisation finale

CreateDocument[
Manipulate[
Which[
Demo==1,cubicSystems,
Demo==2,planeDensities,
Demo==3,closePacking,
Demo==4,exercise1],
{{Demo,1},
{1-> "Systèmes cubiques",
2 -> "Plans cristallographiques",
3 -> "Empilement compact",
4-> "Exercice: indices de Miller"}},LabelStyle->{16,Bold}]
,WindowSize->Full 
(*Pour faire apparaître la fenêtre dans le même bureau, commenter en ajoutant parentheses et asterixes autour de la commande (*,WindowSize->Full*) *)]