.points
: de tre hjørner
.cm
: massemidtpunktet
.color
: farven tegneobjektet skal have. Hvis objektet
får tildelt en ny værdi til denne attribut (fx som det sker
her)
skal klassen sørge for
at såfremt trekanten allerede er tegnet, så opdateres tegneobjektet
for trekanten med den nye farve (se hvordan farven skiftes for noget
tegnet med
fill
i denne how to).
.triangle
: tegneobjektet for trekanten
.cross
: tegneobjektet for et kryds afsat i massemidtpunktet
.draw(ax)
: tegner trekanten i Axis-objektet
ax
. Hvis trekanten allerede er tegnet flyttes
den. Trekanten tegnes med fill
og der afsættes et kryds på
massemidtpunktet.
.move(r)
: flytter trekanten vektoren r
.
P1 = np.array([2,1]) P2 = np.array([4,3]) P3 = np.array([1,4]) points = np.array([P1,P2,P3]) t = Trekant(points) t.draw(ax)
r = np.array([2,1]) t.move(r) fig
t.color = 'orange' fig
t2 = Trekant(points) t2.color = 'chocolate' t2.draw(ax) fig
.plot()
, der flytter knuden på tegningen til den aktuelle
position givet ved attributterne med koordinaterne.
.optimer(all_fjedre)
, der midlertidigt ændrer knudens position ved at
lægge tilfældige tal til hhv - og -koordinaterne. De
tilfældige tal er normaltfordelte omkring nul med en
standardafvigelse på . Efter ændringen af positionen regnes det
ud om energien af fjeder-netværket er gået ned. Er den det
beholdes de nye koordinater. Er den det ikke reetableres de
tidligere koordinater. Hint: husk det med .copy()
for
at få en kopi af et numpy-array og ikke blot endnu et navn for det.
.energi()
, der kan regne energien af fjederen
ud. Fjederkonstanten er og ligevægtslængden er .
.plot()
, der flytter den stiplede streg til den aktuelle
placering af fjederen.
# opret knuderne og gem dem i en liste, hvor indexet har en betydning knuder = [] for i in range(5): knuder.append(Knude()) # fjedrene sidder mellem knuder med disse indices: forbindelser = [[0, 1], [1, 2], [2, 3], [3, 0], [0, 4], [1, 4], [2, 4], [3, 4]] # sæt fjedrene op fjedre = [] for indexA,indexB in forbindelser: knudeA = knuder[indexA] knudeB = knuder[indexB] fjedre.append(Fjeder(knudeA,knudeB))
energi_foer = np.sum([fjeder.energi() for fjeder in fjedre]) N_flytninger = 5 for _ in range(N_flytninger): for knude in knuder: knude.optimer(fjedre) energi_efter = np.sum([fjeder.energi() for fjeder in fjedre]) print(energi_foer,energi_efter)
for knude in knuder: knude.plot() for fjeder in fjedre: fjeder.plot() fig
.r
: walkerens position
.col
: walkerens farve
.move()
: flytter walkeren distancen i en tilfældig retning
.distance()
: returnerer hvor langt walkeren er fra
r
,
altså: skriv np.array([0.,0.])
fremfor
np.array([0,0])
. Ellers kan der nemt opstå et
type-problem for NumPy
hvis den skal starte med heltal
og regne videre med kommatal.
scatter
. Flyt
dem allesammen én gang. Opdatér plottet. Gentag 100
gange.
scatter
får man et
PathCollection
objekt retur. Du
kan lave en generel plotte-funktion, der ser således ud, hvor du selv
skal udfylde for - og -værdierne:
def plot_all_walkers(ax,walkers_to_plot): artist = ax.scatter(# x-værdier # y-værdier color=[w.col for w in walkers_to_plot]) return artist
update
-funktion, som du skriver i forbindelse med
animationen. Det kunne se således ud:
artist.set_offsets([w.r for w in walkers])
.r
: Positionen, , af ilt-atomet i
vandmolekylet.
.theta
: Vinklen, , som bindingen mellem
ilt-atomet og det første brint-atom i vandmolekylet danner til
-aksen. Når .theta
ændres skal attributterne
.r_H1
og .r_H2
genberegnes.
.r_H1
: Den beregnede position af det første brint-atom
når ilt-brint bindingslængden er Å.
.r_H2
: Den beregnede position af det andet
brint-atom. Der skal være vinklen mellem de to
ilt-brint-bindinger i molekylet.
.ax
: Axis-objektet som molekylet er plottet i.
.artists
: En liste med tre Line2D-objekter, en
rød markør i første objekt og to hvide markører i de andre to objekter.
.rattle()
: Når denne kaldes skal ændres med
, hvor .
.draw(new_ax)
: Hvis objektets .ax
attribut endnu ikke er sat
skal den sættes til new_ax
og de tre kugler, en rød og
to hvide, skal tegnes og gemmes som en liste i
.artists
. Hvis new_ax
udelades skal
de tre allerede tegnede kugler (som så kan tilgåes via listen
.artists
)
opdateres til de aktuelle positioner
givet ved .r
, .r_H1
og .r_H2
.
def calculate_total_potential_energy(molecules): W_OO = 0 W_HO = -0.2 W_HH = 0.1 u = 0 for m1 in molecules: r1_O = m1.r r1_H1 = m1.r_H1 r1_H2 = m1.r_H2 for m2 in [m for m in molecules if m != m1]: r2_O = m2.r r2_H1 = m2.r_H1 r2_H2 = m2.r_H2 for r1,r2,W in [(r1_O,r2_O,W_OO), (r1_O,r2_H1,W_HO), (r1_O,r2_H2,W_HO), (r1_H1,r2_O,W_HO), (r1_H1,r2_H1,W_HH), (r1_H1,r2_H2,W_HH), (r1_H2,r2_O,W_HO), (r1_H2,r2_H1,W_HH), (r1_H2,r2_H2,W_HH), ]: u += W / np.linalg.norm(np.array(r1)-np.array(r2)) return u
.rattle()
-metoden for et eller flere af
molekylerne og gentage spørgsmål c). Sammenlign energien for de
forskellige molekyle-arrangementer der opstår. Hvis brint-atomerne peger mod
ilt-atomerne bliver den potentielle energi optimeret, dvs. lavest
muligt. Det ser fx således ud:
for
-løkker. I inderste løkke loopes over alle
molekyler, i yderste løkke loopes over et antal forsøg.
For hvert molekyle i inderste løkke skal du holde styr på vinklen
og molekylernes potentielle energi inden og efter
en ændring af vinklen ved kald af
.rattle()
. Energi-ændringen betegnes . Såfremt energi-ændringen er negativ eller opfylder:
.rattle()
. Metoden der
benyttes kaldes Metropolis Monte Carlo-metoden. Alt efter
værdien af vil den kunne overkomme små barrierer og kunne
optimere en atomar struktur mod en lav-energi struktur. Her vises
energien for 100 af de nestede løkker (2 ydre gentagelser, ét
opdateringsforsøg per molekyle i den inde løkke). I den første halvdel
af simuleringen er . I den anden halvdel er den :
update
, som animation.FuncAnimation
kalder når animationen foretages.
.r
: NumPy array med atomets position.
.artist
: Et Line2D
objekt når atomet
er blevet plottet som en farvet skive.
.plot(ax)
: Plotter atomer som et
Line2D
-objekt
i Matplotlib Axis-objektet, ax
. Skal
gemme Line2D
-objektet som ovennævnte attribut .artist
.
.get_potential_energy(other_atoms)
: Skal beregne energien af alle
de kemiske bindinger af
Lennard-Jones typen, der brydes hvis dette atom
flyttes fra en klynge af atomer givet ved listen af atom-objekter, other_atoms
.
.monte_carlo_step(other_atoms)
: Flytte et atom
en normalt-fordelt distance med amplitude i en vilkårlig
retning. Flytningen accepteres kun såfremt den leder til en lavere
energi eller Metropolis
Monte-Carlo-betingelsen er opfyldt.
.monte_carlo_step(other_atoms)
for ét af
atomerne et antal gange og demonstrér at potentialenergien for
pågældende atom mindskes.
Choose which booklet to go to: