Sei sulla pagina 1di 61

UNIVERSITÀ DEGLI STUDI DI TRIESTE

FACOLTÀ DI INGEGNERIA

Corso di Laurea in Ingegneria Informatica


Tesi di Laurea Triennale

SVILUPPO DI UN FRONT-END GRAFICO


IN .NET PER UN SIMULATORE
MOLECOLARE DPD

Laureando: Relatore:

Filippo MUSCOLINO Prof. Maurizio FERMEGLIA

ANNO ACCADEMICO 2007-2008


Indice

Indice

1 Introduzione........................................................................................4
2 Analisi..................................................................................................6
2.1 La simulazione DPD ................................................................................................. 6
2.1.1 Cenni sulla simulazione molecolare multiscala................................................................... 6
2.1.2 La simulazione mesoscala e DPD........................................................................................... 7
2.2 Analisi del simulatore.............................................................................................. 8
2.2.1 Ambiente nativo ....................................................................................................................... 8
2.2.2 Gestione dell’input/output...................................................................................................... 8
2.2.3 Implementazione ...................................................................................................................... 9
2.2.4 Panoramica sul funzionamento ........................................................................................... 10
2.2.5 Punti critici................................................................................................................................. 12
2.3 Analisi dei requisiti ................................................................................................ 12
2.3.1 Requisiti del simulatore........................................................................................................... 12
2.3.2 Requisiti del front-end............................................................................................................. 13
2.4 Specifica dei requisiti ........................................................................................... 15
2.4.1 Specifiche del simulatore ...................................................................................................... 15
2.4.2 Specifiche del front-end ........................................................................................................ 16
2.5 Portabilità futura .................................................................................................... 21
2.5.1 Linux e Mono ............................................................................................................................ 21
2.5.2 Influenze sulla progettazione e realizzazione .................................................................... 22
2.6 Casi d’uso .............................................................................................................. 22

3 Implementazione ............................................................................26
3.1 Architettura e tecnologie utilizzate...................................................................... 26
3.1.1 Microsoft .NET Framework...................................................................................................... 26
3.1.2 Fortran 90 e interfacciamento.............................................................................................. 27
3.1.3 Schema architetturale ........................................................................................................... 28
3.2 Implementazione del simulatore......................................................................... 29
3.2.1 Direttive per la compilazione in libreria .............................................................................. 29
3.2.2 Gestione dell’output............................................................................................................... 30
3.2.3 Passaggio dell’input ............................................................................................................... 31
3.2.4 Interruzione del programma ................................................................................................. 31
3.2.5 Controllo stato inizializzazione............................................................................................... 32
3.2.6 Subroutine e funzioni introdotte ........................................................................................... 32
3.2.7 Portabilità e vincoli nell’implementazione ......................................................................... 33
3.3 Classe per l’interfacciamento.............................................................................. 33
3.3.1 P/Invoke (Platform Invoke) .................................................................................................... 33
3.3.2 La classe SimulatorDLL............................................................................................................ 34
3.3.3 Approfondimenti ..................................................................................................................... 35

-2-
Indice

3.4 Implementazione del front-end........................................................................... 37


3.4.1 Configurazione del sistema................................................................................................... 37
3.4.2 Salvataggio / caricamento dei parametri ........................................................................ 40
3.4.3 Controllo dei parametri.......................................................................................................... 40
3.4.4 Monitoring e visualizzazione su grafico ............................................................................... 42
3.4.5 Interazione con la simulazione ............................................................................................. 44
3.5 Implementazione interfaccia grafica ................................................................. 45
3.5.1 Struttura ..................................................................................................................................... 45
3.5.2 Usabilità e controlli .................................................................................................................. 46
3.6 Approfondimenti e ulteriori modifiche ................................................................ 47
3.6.1 Utilizzo in ambiente Windows e StackOverflow................................................................. 47
3.6.2 Compilazione in ambiente Linux e relative modifiche.................................................... 47

4 Interfaccia ........................................................................................49
4.1 Installazione / Configurazione ............................................................................. 49
4.2 Esempio di utilizzo ................................................................................................. 49
4.2.1 Immissione dell’input .............................................................................................................. 50
4.2.2 Salvataggio/caricamento dei parametri .......................................................................... 51
4.2.3 Configurazione del programma .......................................................................................... 52
4.2.4 Avvio della simulazione.......................................................................................................... 53
4.3 Testing in ambiente Linux ..................................................................................... 54

5 Conclusioni.......................................................................................56
Bibliografia.............................................................................................58

-3-
Capitolo 1 - Introduzione

Capitolo 1

Introduzione

Premessa
L’applicazione di algoritmi computazionali nel campo dell’Ingegneria Chimica è una metodologia di
lavoro al giorno d’oggi quanto mai diffusa. Il supporto offerto dalle tecnologie viene particolarmente
sfruttato in ambiti che richiedono tecniche quali la modellizzazione e la simulazione.
A tal riguardo, le soluzioni software disponibili sul mercato esistono, tuttavia possono risultare a volte
costose, a volte incomplete. Il problema nasce dall’elevato numero di scenari possibili quando si ha a
che fare con algoritmi di simulazione; per tale motivo, infatti, è facile che spesso ci si rivolga a soluzioni
custom.

Origine del progetto


Il sistema analizzato in questo documento è nato dalla necessità, da parte del Dipartimento di
Ingegneria Chimica dell’Università di Trieste, dell’utilizzo di un simulatore molecolare DPD con specifiche
caratteristiche. L’utilizzo di un tale simulatore è inquadrato all’interno di un progetto europeo, chiamato
“Multipro” (http://www.multipro-f6.eu/), che vede la partecipazione tra le varie università dell’Università
degli Studi di Trieste per l’appunto.
In tale ambito è stata già sviluppata, dal prof. Martin Lisal dell’Accademia delle Scienze di Praga, una
soluzione software per la simulazione molecolare. Essa rispetta le caratteristiche funzionali richieste,
tuttavia non prevede l’esistenza di un front-end grafico che permetta l’interazione con un futuro
utilizzatore dell’applicativo.
E’ da qui che nasce la necessità di mettere in piedi un progetto che preveda l’interfacciamento con la
soluzione precedentemente descritta, in maniera da ottenere un sistema che si collochi
adeguatamente nel contesto universitario.

4
Capitolo 1 - Introduzione

In sostanza si richiede non solo lo sviluppo di un’interfaccia grafica per la gestione dell’applicativo
esistente, ma anche uno studio sull’eventuale portabilità del progetto finale (il progetto d’origine è
infatti sviluppato in ambiente Linux, nell’ambito dell’Università si intende lavorare in ambiente Windows:
la soluzione ottimale consiste in un applicazione multipiattaforma).

La fase di analisi e sviluppo del sistema in esame, svoltasi nell’ambito dell’Università di Trieste, è stata
strutturata secondo i seguenti passi:
1) Chiarimento sugli obiettivi da raggiungere
2) Definizione dei vincoli architetturali e approfondimento sulle tecnologie in uso
3) Studio della soluzione esistente
4) Analisi e specifica dei requisiti del sistema
5) Implementazione dell’interfacciamento e risoluzione problematiche annesse
6) Realizzazione dell’interfaccia grafica
7) Testing e considerazioni sulla portabilità

Breve riassunto dei capitoli successivi


2 Analisi.
Studio approfondito del sistema nel suo complesso. Si parte dalla descrizione della soluzione
esistente per arrivare alla definizione di ciò che si vuole ottenere mettendo in luce i punti
fondamentali del progetto. In questo capitolo vengono definiti requisiti e specifiche
dell’applicazione finale.
3 Implementazione.
Si documenta la fase di realizzazione del front-end, ponendo particolare attenzione sulle tematiche
riguardanti l’architettura del sistema, il collegamento tra front-end e simulatore, e la portabilità.
Vengono approfondite inoltre le problematiche affrontate, tipiche della progettazione e sviluppo di
un sistema basato sull’interfacciamento di due o più soluzioni.
4 Interfaccia.
Descrizione delle modalità di utilizzo dell’applicazione col supporto di screenshot della fase di
testing. Si evidenziano, separandole schematicamente, le funzionalità disponibili in modo da
rendere chiaro il collegamento con la fase di analisi dei requisiti.
5 Conclusioni.
Punto di chiusura con considerazioni sul raggiungimento degli obiettivi e sullo stato finale del
progetto. Breve digressione sulla tipologia delle problematiche affrontate che permette di
generalizzare gran parte del contenuto di questo testo, estendendone l’utilità al di fuori della
semplice documentazione. Si aprono, infine, prospettive e sviluppi futuri sull’evoluzione
dell’applicativo.

5
Capitolo 2 - Analisi

Capitolo 2

Analisi
In questo capitolo si affronta la fase di analisi del progetto. Inizialmente vengono messe in luce le
caratteristiche del simulatore (considerando funzionalità, struttura e requisiti di sistema),
successivamente segue uno studio approfondito dei requisiti richiesti dal progetto (input/output,
interfaccia grafica, portabilità) sino ad ottenere le specifiche di ciascun dettaglio e uno schema
riassuntivo di ciò in cui consiste il progetto finale.

2.1 La simulazione DPD

2.1.1 Cenni sulla simulazione molecolare multiscala

Nell’ambito della scienza dei materiali gioca un ruolo fondamentale l’applicazione di tecniche
computazionali: esse infatti permettono di ottenere una previsione sulle proprietà macroscopiche di
materiali in via di realizzazione. L’importanza di tali tecniche coinvolge principalmente il settore delle
nanotecnologie: si ha a che fare dunque con elementi che presentano almeno una caratteristica
morfologica sulla scala dei nano metri. In questo contesto si collocano le tecniche di simulazione
molecolare.
Gli algoritmi di simulazione molecolare costituiscono, infatti, uno strumento sempre più performante per
lo studio delle proprietà dei nano materiali; tuttavia, le proprietà macroscopiche di un materiale
derivano da caratteristiche su più livelli di scala, sia per quanto riguarda le dimensioni, che i tempi.
Le singole tecniche di simulazione dunque, per quanto sempre più potenti, non permettono di ottenere
un risultato completo.
La soluzione consiste nel combinare assieme più modellizzazioni (e quindi simulazioni) su scale diverse.
Questo è ciò che costituisce una tecnica di simulazione multiscala: si integrano diverse tecnologie di
simulazione, ognuna appartenente a una scala specifica (vedi figura 2.1)

6
Capitolo 2 - Analisi

Figura 2.1 - Tecnica di simulazione multiscala

2.1.2 La simulazione mesoscala e DPD

La simulazione mesoscala è un tipo di simulazione che si interpone tra simulazioni a bassa scala (che
considerano i singoli atomi o addirittura i quanti) e ad alta scala (che considerano proprietà del sistema
nella sua completezza, o il processo completo). Essa si basa sui risultati delle simulazioni a scale inferiori
e al contempo fornisce informazioni che verranno utilizzate nelle modellizzazioni a livello macroscopico.

Il DPD (Dissipative Particles Dynamics) costituisce un metodo computazionale di simulazione mesoscala;


in sostanza è una tecnica che coinvolge un set di particelle in movimento all’interno di uno spazio
continuo e di un tempo discreto. Le particelle rappresentano intere molecole piuttosto che singoli
atomi, difatti in questo tipo di simulazione i dettagli di tipo atomistico non sono considerati rilevanti al
fine del processo che si analizza. Le particelle, inoltre, vengono ricondotte a coppie di forze dissipative
e casuali (da qui il nome).
Il vantaggio principale di questo metodo di simulazione sta nella possibilità di ottenere risultati a lungo
termine e su larga scala rispetto a ciò che si ottiene dalle tradizionali simulazioni molecolari MD
(Molecular Dynamics).

7
Capitolo 2 - Analisi

2.2 Analisi del simulatore


La soluzione software preesistente alla quale si farà riferimento in questo documento è rappresentata
da un applicativo sviluppato da un docente dell’Accademia della Scienze di Praga, il prof. Martin Lisal.
Nei paragrafi successivi viene illustrato brevemente lo stato attuale del progetto, prendendone in
considerazione aspetti strutturali e funzionali; in tal modo si punta a dare una panoramica del contesto
dal quale si intende partire per lo sviluppo del nuovo progetto. La fase di analisi del simulatore, inoltre,
costituisce la base per la successiva fase di ricerca dei requisiti.

2.2.1 Ambiente nativo

L’applicativo è stato sviluppato con il linguaggio Fortran 90 e nasce dall’unione di diversi moduli
realizzati nel corso degli anni. Esso nasce originariamente in ambiente Linux, testato sul compilatore
Fortran gfortran; al dipartimento di Ingegneria Chimica dell’Università (ente per il quale viene realizzato
questo progetto) ad ogni modo viene distribuito il codice sorgente: ciò comporta la possibilità di
compilare ed eseguire il programma anche in ambiente Windows. (Per un corretto funzionamento in
ambiente Windows è comunque consigliata la compilazione con il compilatore gfortran, disponibile
anche per tale sistema operativo)
Allo stato attuale i requisiti per la corretta esecuzione del simulatore sono dunque:
a) Sistema operativo a scelta tra Windows e Linux
b) Compilatore gfortran

2.2.2 Gestione dell’input/output

Il programma si occupa di eseguire un modello di simulazione molecolare DPD (vedi paragrafo 2.1). Il
tempo all’interno della simulazione è misurato in timesteps cioè in intervalli di tempo definiti a priori.

Gestione dell’input
I dati di input sono esplicitati tramite variabili globali all’interno del codice stesso. Gli unici parametri che
possono essere modificati interattivamente dall’utente al momento dell’esecuzione, sono quelli che
vengono definiti control parameters e consistono in:
• durata in timesteps della simulazione
• numero di timesteps ogni quanto viene aggiornato il file di monitoring
• possibilità di riprendere una simulazione interrotta partendo dal file di configurazione associato
• nome del file di configurazione (dove salvare lo stato / dal quale leggere lo stato nel caso si
scelga di riprendere una precedente simulazione)

8
Capitolo 2 - Analisi

Gestione dell’output
L’output viene mostrato durante la simulazione sotto forma di:
• messaggi su console:
o valori iniziali dell’input
o valore dell’energia (iniziale, finale, corrente dopo ogni iterazione)
o numero di iterazioni
o messaggi di errore
• file esterni:
o un file di configurazione (nome scelto dall’utente) contenente lo stato attuale (utile nel
caso si volesse interrompere e riprendere la simulazione)
o un file di monitoring (“monitor.dat”) contenente informazioni sull’andamento di
energia, pressione e temperatura
o più file definiti di tipo RASMOL (estensione “.xyz”) utili all’elaborazione tramite
l’omonimo software esterno (RASMOL per l’appunto)

2.2.3 Implementazione

Segue uno schema dell’implementazione dell’applicativo (vedi figura 2.2). Come si può notare l’input
proviene da più sorgenti, inoltre è fondamentale osservare la distinzione tra le varie tipologie di output
(dall’output generico su console, all’output specifico su file esterni).

Figura 2.2 – Implementazione schematica del simulatore

9
Capitolo 2 - Analisi

2.2.4 Panoramica sul funzionamento

Breve panoramica sul funzionamento del simulatore. L’applicativo viene testato in ambiente Linux (il
suo ambiente originario), compilato tramite il compilatore gfortran. Il file sorgente è chiamato “rdpd-
s_gptms_zns-mptms_1.f90”.

Compilazione ed esecuzione
Il comando per la compilazione è il seguente (da console):

gfortran rdpd-s_gptms_zns-mptms_1.f90

Viene generato un file denominato “a.out” (oppure “a.exe” nel caso ci si trovi in ambiente Windows), si
esegue quindi tale file:

./a.out

Appena avviato il simulatore richiede come input i sopracitati control parameters. Successivamente
restituisce su console una serie di output, relativi alla configurazione iniziale (come si può vedere in
figura 2.3).

Figura 2.3 - avvio del simulatore e output iniziale

Gestione dell’output
L’output dei successivi dati (quali energia, iterazioni, ecc.) viene in parte gestito a livello di console
(come visto sopra) e in parte gestito su file esterni.
Conclusasi una prima fase (pochi minuti di durata) che potremmo definire di inizializzazione, vengono
generati nella cartella del programma diversi nuovi file (vedi figura 2.4), già analizzati nel capitolo 2.2.2.

10
Capitolo 2 - Analisi

Figura 2.4 - file esterni generati dal simulatore

Il contenuto del file “monitor.dat”, ad esempio, dopo alcuni minuti di simulazione consiste in 4 colonne
raffiguranti il timestep (colonna 1), l’energia istantanea (colonna 2), la pressione istantanea (colonna 3)
e la temperatura istantanea (colonna 4), come si può vedere in figura 2.5.

Figura 2.5 - contenuto del file di monitoring

Nel caso in cui un utilizzatore del programma volesse cambiare le variabili di input del simulatore
dovrebbe aprire con un editor di testo il sorgente (“rdpd-s_gptms_zns-mptms_1.f90”), modificare i valori
delle variabili globali (vedi esempio in figura 2.6) e ricompilare il programma come precedentemente
visto.

Figura 2.6 - dati di input del programma sotto forma di variabili globali

11
Capitolo 2 - Analisi

2.2.5 Punti critici

In questa sezione, partendo dallo studio appena effettuato sul simulatore, si va ad eseguire un analisi
dei punti critici del sistema in uso che necessitano di correzioni e/o aggiunte; ciò costituisce il punto di
partenza per la fase di definizione dei requisiti che il front-end è vincolato a rispettare.

1. Immissione dell’input
Il primo problema venuto alla luce durante lo studio del simulatore riguarda l’immissione dei dati di
input; non è infatti plausibile pensare che un utente medio che voglia utilizzare il simulatore debba
conoscere il linguaggio Fortran 90 al fine di modificare i dati di input da introdurre. Inoltre, l’applicativo
va ricompilato ogni qual volta venga modificato l’input, ciò comporta l’impossibilità di prescindere dal
codice sorgente, vincolando la distribuzione di un prodotto “finito” e completo.

2. Visualizzazione dei risultati


I risultati in parte sono mostrati in output su console, in parte sono registrati nei file esterni, come nel caso
del file di monitoring. Inoltre, i valori sono riportati in forma scientifica senza alcun tipo di formattazione,
né vi sono informazioni che descrivano il contenuto dei file esterni (solo leggendo le note dell’autore del
software è possibile risalire al significato di tali valori).

3. Interfaccia utente
L’interfaccia utente è basilare: è costituita dalla classica schermata a console, tipica degli applicativi
che girano sotto shell. Essa denota dunque un approccio poco user-friendly, inoltre permette poca
interattività con l’utente (quest’ultimo a parte inserire da riga di comando i valori dei control
parameters non ha altre funzionalità a sua disposizione).

2.3 Analisi dei requisiti


Basandosi su quanto detto nella precedente sezione, sulle richieste del committente e sulle modifiche
ritenute opportune dall’autore di questo documento, ci si appresta a definire i requisiti che dovrà
soddisfare il progetto finale.

2.3.1 Requisiti del simulatore

1. Vincoli architetturali
Il motore dell’applicazione (l’algoritmo di simulazione) è già stato implementato e distribuito come
codice sorgente; ciò che si richiede è l’interfacciamento al simulatore mantenendo il più possibile
intatto il codice originale. In sostanza le modifiche al codice del simulatore saranno minime e solo se
estremamente necessarie.

12
Capitolo 2 - Analisi

2. Gestione dell’input dall’esterno


I valori di input non saranno più impostati come parametri internamente al programma, ma si vuole che
sia possibile un passaggio dall’esterno di alcuni parametri rilevanti.

3. Interazione con la simulazione


Attualmente per interrompere la simulazione è necessario chiudere la console; tale soluzione risulta
poco elegante, nonché pericolosa: potrebbe accadere che al momento della chiusura il programma
sia nel bel mezzo di un operazione di input/output su file (con conseguenze di un possibile
danneggiamento del file).
Si richiede dunque la possibilità da parte dell’utente di interagire con la simulazione, con la possibilità di
interromperla correttamente se necessario.

Oltre ai requisiti richiesti è stato ritenuto opportuno, da parte dell’autore, introdurre un ulteriore requisito.

4. Gestione di un file di log/result


L’utilizzo del simulatore da console richiede un output continuo in modo da mostrare un feedback
all’utente; da ciò deriva che l’output generato dall’applicativo contiene informazioni sovrabbondanti,
spesso non strettamente utili per l’utente finale che utilizzerà il sistema.
Effettivamente, vi sono informazioni quali il numero di interazione, ad esempio, non fondamentali ai fini
della simulazione in sé. Ciò che conta sono i valori del file di monitoring (che permettono un controllo
dell’andamento della simulazione) e i valori di input e (ovviamente) di output finale.

Per tale motivo si ritiene opportuna la creazione di un file di log/result che permetta all’utente di
controllare i messaggi generati durante la simulazione, nonché i risultati finali.

2.3.2 Requisiti del front-end

1. Vincoli architetturali
In accordo con l’ente committente è stato scelto di realizzare il front-end sulla piattaforma Microsoft
.NET. Questa scelta è stata in parte motivata dallo sviluppo già in passato di applicativi su tale
framework nell’ambito del Dipartimento di Ingegneria Chimica dell’Università di Trieste. (Per un
approfondimento sulle tecnologie utilizzate si rimanda al capitolo 3.1)

2. Immissione dati di input


L’interfaccia grafica ha il compito principale di permettere all’utente l’introduzione dei dati di input per
la simulazione; i dati verranno poi passati al simulatore che li combinerà con altri dati presenti al suo
interno e inizierà la simulazione.

3. Interazione con la simulazione


Dal front-end sarà possibile interagire con la simulazione: si avrà la possibilità di avviare e stoppare la
simulazione, senza preoccuparsi della chiusura manuale del simulatore.

13
Capitolo 2 - Analisi

4. Visualizzazione dati di monitoring


E’ prevista una visualizzazione grafica dell’andamento della simulazione. Vi sarà un controllo in tempo
reale del file di monitoring; i dati acquisiti verranno poi trasformati in forma di grafico per permettere
all’utente di valutare eventuale situazioni anomale e seguire l’evoluzione del processo.

I seguenti requisiti sono stati introdotti dall’autore del progetto, in quanto ritenuti utili ai fini
dell’utilizzabilità e per incrementare le funzionalità dell’applicativo.

5. Possibilità di esportare / importare la configurazione attuale


Al fine di migliorare l’utilizzo del programma è stato deciso di permettere all’utente di esportare i dati di
input immessi, in un file esterno, prevedendo un successivo caricamento degli stessi.
In tal modo sarà possibile all’utente salvare più configurazioni di input, e caricare quella opportuna al
momento della simulazione, risparmiando sicuramente tempo e fatica (nella ricompilazione della form).

6. Gestione degli errori


L’utente deve essere informato sugli errori relativi l’utilizzo sia del front-end, sia del simulatore. Per questo
motivo i messaggi di output di errore del simulatore verranno “catturati” e visualizzati nell’interfaccia
grafica.
Questo è fondamentale in quanto l’utente deve essere sempre messo al corrente di eventuali
malfunzionamenti o situazioni di input scorretto.

7. Visualizzazione stato della simulazione


Poiché l’interfaccia grafica sostituirà la console è bene sostituire in qualche modo i messaggi verbose
(informazioni su tutto ciò che sta facendo l’applicativo) generati dal simulatore durante l’esecuzione.
Per questo motivo è stato ritenuto opportuno visualizzare lo stato della simulazione in tutte le sue fasi
(passaggio di parametri / inizializzazione / avvio della simulazione / fine della simulazione) a livello di
interfaccia grafica.

8. Configurabilità dell’interfaccia
L’utente esperto, che abbia dunque raggiunto un grado di successiva abilità nell’utilizzo
dell’applicazione, può trovare funzionale la possibilità di configurare alcuni parametri dell’interfaccia
grafica, quali i valori di default dei campi della form e la descrizione loro associata.
Per tale motivo si prevede la possibilità di modificare tali valori, andando ad adattare l’applicazione
alle proprie esigenze.

14
Capitolo 2 - Analisi

2.4 Specifica dei requisiti


Ci si appresta a definire approfonditamente le specifiche che dovrà soddisfare il progetto finale, in
termini funzionali e non. Segue dunque un analisi delle specifiche del motore simulatore e
dell’interfaccia grafica.

2.4.1 Specifiche del simulatore

1. Vincoli architetturali
Gli algoritmi di simulazione sono già stati implementati in ambiente Fortran 90; la soluzione che si ha a
disposizione è inoltre testata e funzionante. Ciò porta alla decisione di mantenere l’applicativo in tale
ambiente (escludendo quindi un porting del codice che richiederebbe un costo oneroso in termini di
tempo e lavoro).
I nuovi moduli introdotti che riguardino direttamente la simulazione verranno dunque sviluppati in
Fortran 90.

2. Gestione dell’input dall’esterno


Sarà possibile ricevere dall’esterno i quattro parametri di input precedentemente introdotti da console,
più ulteriori parametri ritenuti rilevanti ai fini della simulazione. Segue l’elenco dei parametri importatibili
dall’esterno, con relativa descrizione fornita dall’autore del simulatore (vedi tabella 2.1).

nrun Number of DPD timesteps


nprint Number of DPD timesteps before printing
cnfile Name of configurational file
If yes, the program starts from a previous run; if no,
yesno
the program creates a starting configuration
Φ NP The volume fraction of nanoparticles
L the length of the cubic simulation box
m1 Mass of a DPD polymer
m2 Mass of a DPD particle of the icosahedron
K Nanoparticle spring costant
D cut Nanoparticle bond-bond cut-off distance
eps GW Polymer Gaussian-Well
r GW Polymer Gaussian-Well position
lambda GW Polymer Gaussian-Well width
K rep Nanoparticle bond-bond repulsion constant
a11 Maximum repulsion between DPD particles i and j
a12 Maximum repulsion between DPD particles i and j
a22 Maximum repulsion between DPD particles i and j

Tabella 2.1 – Elenco dei parametri passabili per input dall’esterno al simulatore

15
Capitolo 2 - Analisi

3. Interazione con la simulazione


Attualmente il programma non prevede l’interruzione della simulazione da parte dell’utente. Per
rendere possibile ciò, si modificherà il codice del programma permettendo l’interruzione del ciclo
principale del programma. E’ bene evidenziare che prima del ciclo principale è presente una fase di
inizializzazione; poiché essa è esterna al ciclo si simulazione (vedi implementazione – capitolo 2.2.3) non
sarà possibile interromperla.
E’ inoltre opportuno restituire un error code ogni qual volta la simulazione viene interrotta per capire se
l’interruzione sia dovuta all’utente, all’input errato, o alla fine corretta del algoritmo.

4. Gestione di un file di log/result


Tutto l’output indirizzato a console (valori iniziali di input, numero di iterazione, ecc.) verrà invece
indirizzato su un file di log/result chiamato “logresult.txt”. Inoltre, tale file conterrà per ogni messaggio di
output una timestamp che indichi data e ora del messaggio, in modo da tenere traccia temporale
dell’output.

2.4.2 Specifiche del front-end

1. Vincoli architetturali
E’ stato scelto il framework Microsoft .NET versione 3.5 (al momento l’ultima versione uscita in termini di
tempo); il linguaggio di programmazione per l’interfaccia sarà il C#, dal momento che già in passato è
stato testato l’interfacciamento tra un applicativo Fortran 90 e un applicativo C# nell’ambito del
Dipartimento.
Il sistema operativo per il quale il progetto è destinato all’uso è Microsoft Windows XP/Vista.

2. Immissione dei dati di input


I dati di input passati al simulatore sono quelli presenti in tabella 2.1.
Verrà realizzata una semplice form che permette l’immissione di tali dati (vedi bozza in figura 2.7)

Figura 2.7 – Bozza di form per immissione input

16
Capitolo 2 - Analisi

3. Interazione con la simulazione


L’interfaccia grafica presenterà dei pulsanti che permettano all’utente di avviare e stoppare la
simulazione. Saranno necessari dei messaggi che specifichino l’effettiva terminazione del simulatore.
Si ritiene inoltre di dover distinguere i casi in cui la simulazione sia stata interrotta manualmente da quelli
in cui l’interruzione sia dovuta ad altri motivi.

E’ importante segnalare l’interruzione della simulazione distinguendone la tipologia: l’utente deve


essere sempre informato su ciò che accade, sullo stato della simulazione. Può accadere che l’utente
richieda l’interruzione della simulazione, ma che essa non abbia ricevuto il segnale e stia ancora
continuando a lavorare. Bisogna dare la certezza dell’avvenuta chiusura, non è sufficiente che sia stato
premuto un tasto ‘stop’.

4. Visualizzazione dati di monitoring


Il front-end prevede la presenza di un grafico che interpreti in tempo reale i valori presenti nel file di
monitoring “monitor.dat”.
Si vuole quindi controllare in tempo reale (o quasi) tale file, registrando ogni cambiamento e
aggiornando il grafico relativo. Il file “monitor.dat” contiene 4 valori:
- timestep
- energia per particella
- pressione globale
- temperatura globale
Per rendere più chiara la visualizzazione verranno visualizzate energia e pressione su un grafico, e la
temperatura su un altro a parte. La scala temporale ovviamente è rappresentata dai timesteps a cui si
fa riferimento.

Si è optato per un grafico a linee con indicatori dei valori. Questo perché, in questo specifico caso, ciò
che conta è mostrare l’andamento in tempo reale di diversi valori controllando la presenza di eventuali
abbassamenti o innalzamenti non motivati. Il grafico serve principalmente per valutare se i parametri
della simulazione denotino un comportamento anomalo, per questo il grafico a linee è ciò che risulta
più utile in questo contesto.

5. Possibilità di esportare / importare la configurazione attuale


Una volta compilata la form per l’immissione dell’input è prevista la possibilità di salvare i parametri
immessi su un file esterno; si vuole che il salvataggio avvenga su un file in formato XML
(http://www.w3.org/XML/), dal momento che tale formato rappresenta una soluzione diffusa per il

salvataggio di dati in formato strutturato.


L’utente avrà la possibilità inoltre di riempire la form importando dati da un file precedentemente
esportato.

17
Capitolo 2 - Analisi

Per ogni valore vengono memorizzati il nome del campo (name) e il valore attuale (value).
La struttura del file XML generato sarà di questo tipo:

<?xml version="1.0" standalone="yes"?>


<DocumentElement>
<parameters>
<name>nome del campo</name>
<value>valore di default</value>
</parameters>
<parameters>
<name> nome del campo</name>
<value> valore di default </value>
</parameters>
[...]
</DocumentElement>

6. Gestione degli errori


L’applicazione comunicherà sia gli errori legati al front-end che quelli legati al simulatore.
Per quanto riguarda il simulatore l’obiettivo è quello di portare all’esterno i messaggi di errore generati
durante l’esecuzione in caso di input errato e acquisirli mostrandoli a livello di interfaccia grafica tramite
le classiche finestre della classe MessageBox. Lo stesso vale per gli errori relativi l’interfaccia grafica
(parametri immessi errati, file di configurazione danneggiato, ecc.)

E’ importantissimo segnalare il tipo di errore all’utente (ed utilizzare un linguaggio per quanto possibile
comprensibile). Ciò migliora l’usabilità del programma, poiché in caso di errori di input verrà segnalato
qual è il valore da modificare.

7. Visualizzazione stato della simulazione


Da front-end sarà possibile visualizzare lo stato della simulazione; si è deciso di tenere conto di quattro
fasi principali:
- passaggio dei parametri
- inizializzazione
- avvio della simulazione
- processo di simulazione in corso

Il passaggio dei parametri avviene al momento in cui il front-end si interfaccia con il simulatore.
L’inizializzazione è la prima fase appena avviato il simulatore, non rappresenta la simulazione vera e
propria, che invece avverrà successivamente; l’inizializzazione, inoltre, può durare anche diversi minuti.
L’avvio della simulazione avviene appena finita l’inizializzazione; ci si accorge di ciò dal momento che
vengono generati il file di configurazione (contenente lo stato della simulazione appena inizializzata) e il
primo dei file RASMOL (quelli con estensione .xyz).

18
Capitolo 2 - Analisi

Se il programma non ha trovato errori esegue il ciclo principale che contiene gli algoritmi di
simulazione; questo ciclo avrà termine se viene interrotto dall’utente (vedi requisiti del simulatore –
capitolo 2.3.1) o se la simulazione è stata portata a termine.
Per ciascuna delle precedenti fasi verrà segnalato l’inizio e la fine, oltre ad un’eventuale interruzione
dell’esecuzione.

8. Configurabilità dell’interfaccia
E’ previsto che l’utente abbia la possibilità di modificare due parametri legati all’interfaccia che sta
utilizzando:
- valori di default dei campi di immissione input
- descrizione associata a tali campi
Si prevede quindi una configurazione di default tipica dell’applicazione, immutabile e compresa
all’interno del codice, e una possibile configurazione custom gestita dall’utente.
L’utente in sostanza può modificare i parametri della configurazione di default salvando le nuove
impostazioni su un file esterno “default.xml” (sempre XML quindi) che si troverà in una directory
prestabilita. Al momento di avviare il programma ci sarà un controllo sull’esistenza e la correttezza del
file default.xml: se il file esiste ed è integro (la struttura non è danneggiata ed i valori sono consistenti)
allora verrà caricata la configurazione custom, altrimenti si caricherà la configurazione di default
prevista dal programma.
Verranno dunque salvati il nome del campo di riferimento (name), il valore di default (defaultVal) e la
descrizione associata (description).

Un esempio di file configurazione “default.xml” è il seguente:

<?xml version="1.0" standalone="yes"?>


<DocumentElement>
<configuration>
<name>tB_nrun</name>
<defaultVal>100000</defaultVal>
<description>Number of DPD timesteps</description>
</configuration>
<configuration>
<name>tB_nprint</name>
<defaultVal>500</defaultVal>
<description>Number of DPD timesteps before printing</description>
</configuration>
[...]
</DocumentElement>

19
Capitolo 2 - Analisi

9. Struttura interfaccia grafica


In base a quanto visto l’interfaccia grafica dovrà presentare 4 moduli principali:
- immissione dati input
- visualizzazione stato simulazione
- grafico dell’andamento in realtime
- configurazione parametri dell’interfaccia

Si può abbozzare una struttura indicativa rappresentata nelle successive figure 2.8 e 2.9.

Figura 2.8 - bozza della schermata principale

Figura 2.9 - bozza della schermata di configurazione

L’ente che ha commissionato il progetto non ha dichiarato particolari vincoli di realizzazione


dell’interfaccia grafica.
L’autore del progetto ha ritenuto comunque opportuno introdurre due vincoli legati alla funzionalità:
- Presenza della barra menu in alto (per rendere accessibili tutte le funzioni)
- Presenza della barra di stato in basso (per mostrare i messaggi di descrizione associati ai campi
che aiutano a capire come utilizzare l’applicazione)

20
Capitolo 2 - Analisi

2.5 Portabilità futura


Durante la fase di analisi del simulatore è stato evidenziato come l’applicativo originale sia stato
sviluppato in ambiente Linux. E’ stato pertanto deciso di seguire una strada di sviluppo per il front-end
(a partire dalle specifiche stesse) che preveda la massima portabilità del progetto per tale sistema
operativo.

Questa scelta risulta spesso cruciale al momento di progettare e realizzare una soluzione software;
bisogna tenere in considerazione un rapporto costi/benefici poiché talvolta il costo per l’utilizzo di una
tecnologia anziché di un’altra può risultare elevato.
D’altro canto i vantaggi di una applicazione, definita portabile (riutilizzabile quindi sotto un ambiente
diverso da quello nativo), sono molteplici: si va da una maggiore diffusione (fondamentale nel caso di
soluzioni commerciali) a un maggiore supporto nello sviluppo (nel caso di soluzioni open source in via di
realizzazione o completamento). Senza considerare poi che per realizzare un progetto portabile
bisogna molto spesso (non sempre) ricorrere all’utilizzo di tecnologie standard, quindi universalmente
riconosciute e seguenti regole ben definite.

In seguito si approfondisce il tema della portabilità sotto Linux prendendo in esame le soluzioni esistenti
in merito ad ambienti di sviluppo e le strade percorribili in tale senso.

2.5.1 Linux e Mono

Il principale obiettivo che ci si pone è dunque la massima portabilità dell’applicativo verso sistemi
operativi di tipo Linux.
In questo caso si parla di massima portabilità intendendo la possibilità di riutilizzo del software in tale
ambiente con il minor numero di modifiche possibili (in sostanza con il minor costo): è bene precisare,
infatti, che il porting richiede quasi sempre modifiche al codice, nonostante la portabilità ideale sia
rappresentata da un’applicazione riutilizzabile senza modifiche.

Al momento di definire i vincoli architetturali del progetto è stato deciso di optare per lo sviluppo su
framework Microsoft .NET. Questa piattaforma, sebbene di tipo proprietario, permette la portabilità in
ambiente Linux sfruttando un progetto abbastanza recente (nato circa 4 anni fa) chiamato “Mono”.
Senza entrare troppo nel dettaglio, Mono (http://mono-project.com/What_is_Mono) si può definire come un
progetto open source che mette a disposizione diversi strumenti (dall’ambiente di sviluppo a una
macchina virtuale) per la creazione ed esecuzione di applicativi multipiattaforma compatibili con il
framework .NET.
La compatibilità è ottenuta grazie alla presenza di un’insieme di librerie, messe a disposizione,
compatibili con quelle del framework di casa Microsoft. Il linguaggio originariamente supportato
dall’ambiente di sviluppo incluso nel progetto (chiamato “Monodevelop”) è il C#, sebbene
recentemente sia stato introdotto il supporto ad altri linguaggi (Java e Python per citarne alcuni).

21
Capitolo 2 - Analisi

2.5.2 Influenze sulla progettazione e realizzazione

La strada appena messa in luce si traduce concretamente nella scelta di tecnologie, metodologie e
strumenti che supportino la portabilità dell’applicativo.
I vincoli architetturali sono compatibili con la direzione presa (utilizzo di piattaforma .NET, linguaggio di
programmazione C#) e la stessa fase di specifica dei requisiti del front-end tiene da conto questa
scelta.

Un esempio è rappresentato dall’utilizzo del linguaggio XML per la gestione dei parametri di input e di
configurazione dell’interfaccia, in quanto XML rappresenta di per sé uno standard riconosciuto dal
W3C (http://www.w3.org/Consortium/). La sua diffusione difatti è passata dall’ambito del web ad ambiti
più generici quali il passaggio di informazioni tra sistemi diversi, la definizione della struttura di un
documento, e molteplici altri.

La successiva fase di realizzazione (vedi capitolo 3) mostrerà concretamente in che termini la scelta
della portabilità abbia influito sulle tecniche e gli strumenti utilizzati.
La fase di progettazione evidenzierà dei progressivi test anche in ambiente di sviluppo monodevelop, in
modo da controllare passo passo che la strada intrapresa sia quella corretta ai fini degli obiettivi che ci
si è imposti di raggiungere.

2.6 Casi d’uso


Al fine di riassumere schematicamente le fasi di analisi e specifica dei requisiti, e per una maggiore
chiarezza e semplicità, si va ad introdurre una descrizione dei casi d’uso del progetto (servendosi di
semplici schemi e di diagrammi UML).

Figura 2.10 - Diagramma UML Use Case del front-end

22
Capitolo 2 - Analisi

I casi d’uso del front-end sono i seguenti:


- Modifica parametri di input
- Caricamento/salvataggio dati della form di input
- Customizzazione dell’interfaccia
- Interazione con la simulazione

Modifica dei parametri di input

- I parametri vengono letti dai campi della form


- Viene effettuato un controllo dell’input immesso (non devono esserci campi vuoti e il tipo di
input deve essere coerente con la tipologia specificata per il campo)
- Viene effettuata una conversione dei parametri (il valore letto nel campo viene convertito
nella tipologia di destinazione: intero, stringa, ecc.)
- Vengono passati i parametri al simulatore (tramite un’apposita funzione)

Salvataggio / caricamento dati nella form di input

Salvataggio:
- Vengono letti i valori dei campi contenenti la form
- Vengono salvati su file XML in forma (strutturata dunque) nome del campo e valore associato

Caricamento:
- Viene effettuato un controllo sull’esistenza del file
- Viene caricato il file XML tramite un parser XML preesistente
- Viene controllata l’integrità della struttura (il file non deve essere corrotto né deve aver subito
modifiche che ne hanno alterato la struttura)

23
Capitolo 2 - Analisi

- Campo per campo si controlla l’esistenza effettiva del controllo a cui si fa riferimento nel file
- Si imposta il valore del controllo trovato usando quello caricato dal file

Customizzazione dell’interfaccia

La customizzazione dell’interfaccia prevede due alternative:


- Il salvataggio di una nuova configurazione
o Vengono letti i dati di default
o Viene creata una form per la modifica di tali dati (valori di default e descrizione di
ciascun campo)
o Vengono salvati su un file “default.xml” i dati di questa nuova form
- Il caricamento di una configurazione
o I valori possono venire caricati da una configurazione precedentemente salvata
 Viene controllata l’esistenza del file “default.xml”
 Viene letto il file ed effettuato il parsing
 Viene controllata l’integrità della struttura
o I valori possono venire caricati dalla configurazione di default
o Viene aggiornata l’interfaccia coi valori appena caricati (vengono quindi aggiornati i
valori di default dei campi della form di input e le descrizioni associate)

24
Capitolo 2 - Analisi

Interazione con la simulazione

Al momento ho due possibili tipologie di interazione:


- Avvio simulazione
o Vengono passati i parametri di input
o Viene avviato il codice del simulatore (quindi l’inizializzazione)
- Stop simulazione
o Il simulatore riceve una variabile che comunica la richiesta di stop
o Viene effettuato un controllo sullo stato della simulazione finché non si è certi che la
simulazione sia stata effettivamente interrotta
o Viene controllato il codice d’errore generato dal simulatore per capire se l’interruzione
è effettivamente avvenuta per la richiesta o per altri motivi
o Viene gestito a livello di interfaccia grafica un messaggio contenente la descrizione
del motivo dell’interruzione

25
Capitolo 3 - Implementazione

Capitolo 3

Implementazione

In questo capitolo si definisce la fase di realizzazione del progetto, analizzandone approfonditamente


l’implementazione.
Vengono messe in luce le scelte architetturali alla base della realizzazione stessa, i passaggi che hanno
caratterizzato lo sviluppo del front-end, lo studio che sta dietro la progettazione dei singoli moduli,
nonché le problematiche insorte e affrontate
Oltre che costituire una documentazione del lavoro svolto, questo capitolo intende fornire un’utile
analisi sulle scelte progettistiche, che intercorrono al momento di realizzare un sistema di
interfacciamento tra due applicativi provenienti da ambienti eterogenei.

3.1 Architettura e tecnologie utilizzate

3.1.1 Microsoft .NET Framework

La piattaforma .NET
Come precedentemente accennato in altri capitoli, è stato scelto di sviluppare il front-end sulla
piattaforma di sviluppo Microsoft .NET.
Senza entrare troppo nello specifico, il Microsoft .NET Framework è una piattaforma per lo sviluppo e
l’esecuzione di applicativi basati sulla tecnologia .NET (http://www.microsoft.com/net/). Si compone
sostanzialmente di una Base Class Library, una libreria di classi disponibili per diverse funzioni, un insieme
di compilatori per i linguaggi supportati (C#, J#, Visual Basic.Net, i principali) e un ambiente di
esecuzione virtuale, il CLR (Common Language Runtime) che fornisce le funzionalità di una Virtual
Machine (seguendo le specifiche di uno standard chiamato CLI – Common Language Infrastructure).

26
Capitolo 3 - Implementazione

I compilatori, infatti, compilano il codice in un linguaggio definito CIL (Common Intermediate


Language) destinato al CLR; sarà quest’ultimo a tradurlo al tempo di esecuzione in linguaggio
macchina (vedi figura 3.1).

Figura 3.1 – Sviluppo ed esecuzione di codice su framework .NET

In combinazione con il framework si ha a disposizione una suite di strumenti per lo sviluppo degli
applicativi su tale piattaforma: Microsoft Visual Studio.
La realizzazione del front-end è stata effettuata utilizzando la versione 2008 di Microsoft Visual Studio,
mentre la versione del framework .NET è la 3.5.
Il linguaggio di programmazione scelto è il C#, linguaggio orientato alla programmazione ad oggetti
nativamente supportato dalla piattaforma .NET.

3.1.2 Fortran 90 e interfacciamento

Il linguaggio Fortran
Il Fortran 90 è un linguaggio di programmazione, evoluzione dell’originario Fortran (Formula Translation).
Il Fortran fu uno dei primi linguaggi di programmazione ad alto livello e nacque, come suggerisce il
nome stesso, per un utilizzo destinato all’ambito scientifico (implementazione di formule matematiche in
algoritmi computazionali).

Compilazione in ambiente nativo / compilazione su framework .NET


Il Fortran non risulta tra i linguaggi nativamente supportati dalla piattaforma .NET, tuttavia esiste una
soluzione commerciale che permette la compilazione di codice Fortran in ambiente .NET: il compilatore
“Lahey Fortran 7.1 Enterprise” (http://www.lahey.com/).
L’alternativa, d’altra parte, resta la compilazione in ambiente nativo (quindi un oggetto strettamente
dipendente dalle API del sistema operativo dove viene compilato) e il successivo interfacciamento
dall’esterno del framework. In questo caso la scelta sul compilatore è meno vincolante: si possono
usare il già citato gfortran (http://gcc.gnu.org/wiki/GFortranBinaries), o una soluzione commerciale che offre

27
Capitolo 3 - Implementazione

il supporto al tool di sviluppo Microsoft Visual Studio: il compilatore “Intel Visual Fortran 11.0 Professional
Edition” (http://www.intel.com/cd/software/products/asmo-na/eng/compilers/), evoluzione del predecessore
Compaq Visual Fortran.
Nonostante i benefici offerti da una compilazione in ambiente .NET (tramite la soluzione Lahey Fortran),
è stato deciso, in accordo con l’autore del simulatore, di prediligere il secondo scenario: front-end su
piattaforma .NET, simulatore compilato nativamente.
In tal modo resterà possibile per l’autore del simulatore compilare il sorgente con la soluzione originaria
(compilatore gfortran), rendendo quindi più semplici eventuali sviluppi futuri del codice stesso (in
seguito a migliorie o interventi di manutenzione).

Interfacciamento del simulatore con il front-end


L’operazione di interfacciamento consiste nel mettere in comunicazione i due applicativi (interfaccia e
simulatore) rendendo possibile non solo il passaggio di dati (vedi parametri di input), ma anche le
chiamate a funzioni e procedure (vedi l’interazione con la simulazione).
La soluzione per incorporare codice all’interno di un programma è rappresentata dalle librerie, che per
l’appunto altro non sono che un file contenente codice compilato pronto ad essere utilizzato in un
applicativo.
Si è deciso dunque di compilare il simulatore come una libreria dinamica (detta anche condivisa); in tal
modo al momento di lanciare l’esecuzione del front-end il sistema si occuperà di caricare in memoria il
codice del simulatore e collegarlo alla copia del front-end presente anch’essa in memoria.

Il vantaggio più grande nell’utilizzo di una libreria dinamica è la possibilità di modificare il simulatore
(editando il sorgente e ricompilandolo) senza essere costretti a ricompilare il front-end (questo a patto
che non vengano cambiate le interfacce delle subroutine o delle funzioni condivise da entrambi).

3.1.3 Schema architetturale

Figura 3.2 - Architettura finale ed esempio di portabilità su Linux

28
Capitolo 3 - Implementazione

Utilizzo finale
- il simulatore viene compilato in ambiente Windows utilizzando un compilatore a scelta tra Intel
Visual Fortran e Gfortran; le direttive passate al compilatore prevedono la creazione di una
libreria dinamica (file con estensione “.dll” - Dynamic Link Library)
- il front-end è sviluppato in linguaggio C#, in ambiente di sviluppo Visual Studio, ed è compilato
dal compilatore interno (che genera un oggetto in CIL)
- il front-end è collegato alla libreria del simulatore grazie alle funzionalità di una libreria delle
Base Class Library fornite dal framework (vedi capitolo 3.3 per approfondimenti)
- Al momento dell’esecuzione la libreria viene caricata in memoria dal sistema e contiene
codice eseguibile direttamente; il front-end invece viene eseguito in un ambiente virtuale, il
CLR, che si occupa della conversione da CIL a linguaggio macchina adatto all’hardware
specifico.

Esempio di portabilità futura


- Il simulatore viene compilato in ambiente Linux utilizzando il compilatore Gfortran; viene creata
una libreria condivisa (file con estensione “.so” – Shared Object)
- il front-end sviluppato in C# viene aperto nell’ambiente di sviluppo Monodevelop e compilato
col compilatore interno (che genera un oggetto in CIL)
- il front-end è collegato alla libreria del simulatore grazie alle funzionalità di una libreria fornita
dalle Base Class Library di Mono (compatibili con quelle del framework .NET)
- Al momento dell’esecuzione la libreria viene caricata in memoria dal sistema, mentre il front-
end viene eseguito nell’ambiente virtuale Mono Runtime, che converte il CIL in linguaggio
macchina
Ovviamente tutto ciò potrebbe richiedere delle opportune modifiche al codice C# del front-end e/o al
codice sorgente del simulatore.

3.2 Implementazione del simulatore

3.2.1 Direttive per la compilazione in libreria

Al fine di compilare il codice come una libreria dinamica è necessario:


1) Far diventare il modulo principale una subroutine
- Semplice modifica ai due statement “program” e “end program”
2) Introdurre le direttive per il compilatore per sapere quali subroutine esportare all’esterno
- Le direttive da introdurre in una subroutine (o function) per l’interfacciamento con l’esterno
sono del tipo:

!DEC$ ATTRIBUTES DLLEXPORT::nome_della_sub

- Volendo è possibile aggiungere anche la seguente direttiva:

!DEC$ ATTRIBUTES ALIAS:'alias_scelto' :: nome_della_sub

29
Capitolo 3 - Implementazione

Approfondimento
Le subroutine (o funzioni) esportate, infatti, presentano un nome all’esterno che raramente coincide
con quello all’interno del codice Fortran. Ciò varia da compilatore a compilatore. Se il compilatore
supporta la proprietà ALIAS è possibile definire a priori il nome che avrà la subroutine all’esterno.

NOTA: Nel caso si voglia controllare il nome delle sub e funzioni esportate all’esterno da una dll è
possibile utilizzare lo strumento “dumpbin.exe”. Per utilizzare tale strumento aprire il prompt dei comandi
di Visual Studio e digitare:

dumpbin /exports nome_della_dll

3.2.2 Gestione dell’output

Poiché il simulatore non lavorerà più su console, è necessario reindirizzare l’output originariamente su
console in output su file di log.
Per fare ciò è necessario:
1) predisporre un file di log che viene aperto prima dell’inizializzazione e chiuso a fine simulazione
2) convertire le print su console in write su tale file

Approfondimento
1) All’inizio della subroutine principale è stata introdotta l’apertura del file di log:

open (30,file="logresult.txt",access="append",status="unknown")

Si apre il file di log in modalità append (scrivo aggiungendo righe) e unknown (se il file esiste aggiungo
righe a quello esistente, altrimenti ne creo uno nuovo); il primo parametro rappresenta un numero
associato al puntatore al file, permetterà successivamente di scrivere sul file senza dover specificare
nuovamente il nome. A fine simulazione si chiude il file con l’istruzione close.

2) Da un’attenta analisi del codice si è giunti alla conclusione che l’output su console è di due
tipologie:
a) output generico, del tipo:

print *, testo_o_valore

Concentrato unicamente nella subroutine chiamata “output”.

b) output di valori, del tipo:

print testo_che_descrive_il_valore, valore

Presente in diverse parti del listato, all’interno di più subroutine.

Le print del tipo b), poiché concentrate in un'unica porzione del codice ed essendo di tipologie diverse
(valori formattati, non formattati, testo), vengono direttamente sostituite in scritture sul file di log:

write (30, testo_o_valore)

Le print del tipo a) invece, al fine di modificare meno possibile il codice, vengono sostituite da una
subroutine chiamata “myprint” che si occuperà di scrivere su file di log.

30
Capitolo 3 - Implementazione

Passaggio dell’input
Alcuni parametri di input per la simulazione vengono ricevuti dall’esterno, per gestire la ricezione
dall’esterno di parametri è necessario:
1) Trasformare i parametri in variabili globali posizionate all’interno di un modulo
2) Introdurre una subroutine che riceva come argomenti i parametri di input, e assegni alle
variabili globali appena definite il rispettivo valore ricevuto dall’esterno
3) Rimuovere la sezione in cui si leggono alcuni parametri da console (i control parameters – vedi
capitolo 2.2.2), poiché anch’essi verranno introdotti dall’esterno.

Approfondimento
1) E’ stato creato un modulo chiamato “global_data” che conterrà variabili globali usate dalle nuove
subroutine e funzioni, nonché dal programma principale.
I valori di input, definiti originariamente come parametri (con valore quindi esplicitato) diventano
variabili globali all’interno del nuovo modulo creato (senza quindi un valore di default).

2) E’ stata creata una funzione chiamata “load_input” che riceve come argomenti i valori di input,
assegna tali valori alle rispettive variabili (contenute in “global_data”) e alla fine restituisce il valore true.

3) Vengono rimosse tutte le “read”, dal momento che non vi è più interazione con la console.

3.2.3 Interruzione del programma

Il codice sorgente presentava controlli sull’input immesso sia all’interno della subroutine principale, sia
all’interno di altre subroutine; ogni qualvolta non si verificasse una condizione stabilita il programma
veniva interrotto dall’istruzione “stop” (seguita da una descrizione dell’errore da mostrare a console).
Inoltre, la simulazione è strutturata in modo da non poter essere interrotta dall’utente, se non chiudendo
l’applicazione.
E’ necessario, ai fini dell’utilizzo come libreria del simulatore:
1) Scrivere la descrizione dell’errore su un file esterno (poiché non è più disponibile la console)
2) Modificare le istruzioni di “stop” con istruzioni di “return”.
3) Introdurre all’interno del ciclo principale di simulazione un controllo che preveda la possibilità di
interrompere il ciclo (e quindi uscire dal programma)

Approfondimento
1) E’ stata creata una nuova subroutine chiamata “mystop” che riceve come argomento un
messaggio di testo e crea un file chiamato “errore.log” dove scrive il messaggio ricevuto.
E’ stata inoltre introdotta una variabile chiamata “errorCode” che rappresenta un codice restituito
dall’applicazione al momento di terminare; essa è utile per distinguere le interruzioni dovute ad errore,
dalla terminazione dovuta alla fine effettiva della simulazione. Il valore di default di “errorCode” è 0
(simulazione terminata correttamente), la funzione mystop imposta il valore di “errorCode” a -1
(interruzione dovuta ad errori). Inoltre, è stata creata una funzione chiamata “getErrorCode” che
restituisce il valore della variabile “errorCode”.

31
Capitolo 3 - Implementazione

2) Lo statement “stop” non può essere utilizzato all’interno di una libreria, poiché una volta eseguito
restituisce il controllo al sistema operativo, interrompendo dunque non solo il codice della libreria, ma
anche dell’applicazione chiamante.
Per evitare che l’applicazione chiamante venga chiusa quando si interrompe la libreria è necessario
sostituire le “stop” con le “return” (restituisce il controllo al codice chiamante).
Tutte le stop sono state dunque sostituite da chiamate alla funzione “mystop” e successiva return.

3) E’ stata introdotta una variabile globale chiamata “simulStop”, di tipo booleano, con valore di
default settato a false. E’ stato introdotto all’interno del ciclo principale un controllo sulla variabile
simulStop, se essa viene settata a true il ciclo si interrompe e il programma esce con una chiamata a
“mystop” e successiva “return”.
E’ stata inoltre creata una funzione chiamata “AbortSimul” che permetta di settare tale variabile a true
dall’esterno.

3.2.4 Controllo stato inizializzazione

Il codice della subroutine principale può essere suddiviso in due macrosezioni (vedi capitolo 2.2.3): una
rappresenta una fase di inizializzazione, l’altra rappresenta la simulazione vera e propria. Si ritiene utile
introdurre una funzione che restituisca l’avvenuta o meno dell’inizializzazione, in modo da distinguere
l’inizio e la fine delle due fasi.

Approfondimento
La scelta di introdurre una funzione di questo tipo è dovuta anche all’impossibilità di interrompere la
fase di inizializzazione. Poiché si è voluto modificare il meno possibile il codice originale si è preferito non
dividere la subroutine principale in due subroutine dedicate a inizializzazione e simulazione; si è optato
invece per l’introduzione di una variabile booleana “initialized”, settata di default a false, che una volta
finita la prima fase viene settata a true.
E’ stata inoltre creata una funzione chiamata “isInitialized” che restituisce il valore della sopracitata
variabile, in modo da poter controllare lo stato dell’inizializzazione anche dall’esterno.

3.2.5 Subroutine e funzioni introdotte

Si riportano le subroutine/funzioni introdotte, con breve descrizione esplicativa.

- logical function load_input (elencoValoriDiInput)

Riceve dall’esterno i valori di input e li assegna alle rispettive variabili (globali)

- subroutine mystop (error)

Scrive su un file “error.log” la descrizione dell’errore

- subroutine init_log ()

Inizializza il file di log/result con i valori passati per input

32
Capitolo 3 - Implementazione

subroutine myprint (desc,val)

Scrive su file di log il nome del parametro (desc) e il suo valore (val)

- subroutine abortSimul ()

Setta a true simulStop, in modo da interrompere il ciclo principale di simulazione

- integer function getErrorCode ()

Restituisce il valore della variabile errorCode

- logical function isInitialized ()

Restituisce il valore della variabile initialized

3.2.6 Portabilità e vincoli nell’implementazione

Le modifiche al codice sorgente, illustrate e approfondite nei capitoli precedenti, sono il frutto oltre che
di uno studio dei requisiti, anche delle previsioni di portabilità per l’applicativo finale.
Si riporta un esempio nel paragrafo seguente.

Gestione messaggi di errore


Un’alternativa per la gestione dei messaggi d’errore è costituita dall’utilizzo della libreria dfwin,
disponibile nel compilatore Intel Visual Fortran, che mette a disposizione finestre di dialogo del tipo
MessageBox. La soluzione è anche una soluzione elegante poiché è possibile passare all’applicazione
l’handle dell’applicazione chiamante (il puntatore alla finestra), in modo da bloccare la finestra
chiamante nel momento in cui viene fatta comparire la MessageBox.
Tuttavia, questa libreria non è supportata dal compilatore Gfortran dal momento che:
a) è l’evoluzione della libreria dflib distribuita dal predecessore del compilatore Intel Visual Fortran,
il Compaq Visual Fortran (CVF).
b) si appoggia alle API win32.
Per tali motivi si è preferito adottare una soluzione differente (vedi capitolo 3.2.4).

3.3 Classe per l’interfacciamento

3.3.1 P/Invoke (Platform Invoke)

Platform Invoke (spesso abbreviato P/Invoke) è una tecnica che permette l’esecuzione di codice
unmanaged, contenuto ad esempio all’interno di una DLL, da parte di codice managed (quali il C#
per l’appunto).
NOTA: Gli applicativi sviluppati all’interno del framework .NET contengono codice definito managed;
questo poiché il programma in assembly (cioè in CIL) ottenuto come risultato della compilazione viene
eseguito in un ambiente virtuale dove sono possibili diversi controlli (sicurezza in primis). Per contro, il
codice al di fuori del framework come le DLL (che altro non sono che codice nativo basato su API
win32, nel caso di Windows) viene detto codice unmanaged, perché eseguito senza controlli.

33
Capitolo 3 - Implementazione

Per utilizzare le funzionalità del Platform Invoke bisogna:


1) aggiungere il namespace “System.Runtime.InteropServices”

using System.Runtime.InteropServices;

2) utilizzare l’attributo “DllImport” specificando la libreria di riferimento

[DllImport("dpdsimulator.dll")]

3) definire l’interfaccia della funzione da chiamare

static extern void rdpd();

(NOTA: la funzione che si vuole importare con DllImport deve essere definita static, inoltre bisogna
aggiungere l’attributo extern che esplicita come il metodo sia implementato all’esterno).

3.3.2 La classe SimulatorDLL

La classe “SimulatorDLL” è quella che si occupa dell’interfacciamento vero e proprio con il simulatore.
E’ composta dai metodi importati dalla libreria, contenenti quindi codice unmanaged, e da metodi
propri, che sono quindi metodi managed. (Vedi figura 3.3, i metodi evidenziati sono quelli importati)

Figura 3.3 - Diagramma della classe SimulatorDLL

Campi principali
I campi della classe sono tre (tutti private) e rappresentano:
- private int errorCode
il codice d’errore restituito al momento di interruzione del simulatore
- private bool stopped
lo stato del simulatore (avviato o non avviato?)
- private Thread thrd
il thread associato al simulatore (vedi paragrafo successivo)

34
Capitolo 3 - Implementazione

Metodi principali
- private void run()

Avvia il simulatore. Successivamente (cioè quando il codice del simulatore sarà terminato), effettua
un controllo sul codice di errore (usando “getErrorCode” – vedi capitolo 3.2.6) e in base al risultato:
a) mostra un messaggio di avvenuta simulazione
b) controlla l’esistenza del file di errore e mostra il messaggio di errore
Infine setta a true “stopped” e termina il thread.
- public bool setSimInput

Passa i parametri di input chiamando la funzione “load_input” della libreria del simulatore.
Restituisce lo stesso valore booleano restituito dalla “load_input”.
- public void start()

Istanzia il thread associato alla “run” e lo avvia. Setta a false la “stopped”.


- public void stop()

Chiama la subroutine “abortSimul”. Successivamente verifica l’avvenuta terminazione controllando


con un intervallo di 1s se l’errorCode è stato modificato. La sua esecuzione termina effettivamente
solo al momento dell’avvenuta modifica dell’errorCode.
(NOTA: quando l’errorCode viene portato a -1 vuol dire che c’è stata un interruzione nella
simulazione, non dovuta alla fine dei calcoli)

3.3.3 Approfondimenti

Multi
Un’applicazione MultiThread è strutturata in modo da permettere la suddivisione del programma stesso
in task eseguibili in maniera concorrenziale. Ciò risulta particolarmente utile nel caso si debba eseguire
una porzione di codice dalla durata significativamente elevata, avendo necessità di compiere nel
frattempo altro lavoro.
Il sistema che si è andati a progettare prevede l’esecuzione di algoritmi computazionali che possono
durare ininterrottamente anche per giorni (questa è una caratteristica di gran parte degli algoritmi di
simulazione). Lo sviluppo di un’applicazione strutturata in un unico thread porterebbe a conseguenze
quali l’inutilizzo del front-end durante l’esecuzione della simulazione (quindi, come detto, per tempi
decisamente lunghi). Per questo motivo è stata scelta la strada del multiThreading.

Per utilizzare la tecnologia MultiThread in ambiente .NET è sufficiente utilizzare gli strumenti forniti dalla
classe “System.Threading”. Segue un breve esempio delle funzionalità messe a disposizione:

thrd = new Thread(new ThreadStart(metodo_da_eseguire));

Per avviare e terminare il thread:

thrd.Start();
thrd.Abort();

All’interno del metodo è possibile introdurre un’istruzione per metterlo in pausa un certo numero di ms:

thrd.Sleep(tempo_in_millisecondi);

35
Capitolo 3 - Implementazione

Passaggio di parametri
Al momento del passaggio di parametri da un codice ad un altro bisogna tenere conto di:
a) Che tipo di passaggio di parametri utilizzano (per valore o riferimento?)
b) Quali tipologie di dati definiscono (esiste il tipo float? E il tipo string?)

a) In C# ho tre tipologie di passaggio di parametri: in, out, ref. Sostanzialmente con in la variabile viene
passata per valore e non viene modificata durante la chiamata, con out la variabile viene passata per
argomento e settata all’interno della procedura chiamata e con ref la variabile viene sempre passata
per riferimento, ma va settata prima del passaggio. Di default è implicitamente usato in.
In Fortran la situazione è diversa: le variabili vengono passate generalmente (poi ci sono casi specifici)
per riferimento. Per questo motivo tutte le variabili passate da C# a Fortran dovranno essere specificate
come ref.

b) I datatypes (tipologie di dati) del Fortran, differiscono da quelli del C# (in generale del C). Per
esempio si riporta una tabella con alcune differenze:

FORTRAN C

integer*2 short int

logical bool

real float

real*8 double

Inoltre, in Fortran le stringhe sono considerate come array di caratteri. Tuttavia è comunque possibile
passare una string utilizzando un espediente che viene chiamato “hidden length”: oltre a passare il
riferimento alla string si passa anche la lunghezza della stringa. Questo parametro, sebbene non sia
presente nell’interfaccia della subroutine/funzione chiamata, è necessario al Fortran a istanziare l’array
di caratteri che conterrà la stringa.

Threading e unmanaged code


Altro punto da tenere in considerazione quando si ha a che fare con chiamate a codice unmanaged
riguarda la gestione dei thread. Difatti, è possibile associare codice unmanaged a un thread
managed, tuttavia è importante sapere che non è possibile terminarne l’esecuzione in qualunque
momento.
Citando la documentazione del metodo “Abort” della classe “Thread”:

If Abort is called on a managed thread while it is executing unmanaged code, a ThreadAbortException


is not thrown until the thread returns to managed code.

(fonte: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx)

In sostanza il sistema terminerà il thread (sollevando l’eccezione ThreadAbortException) solo al


momento della fine del codice unmanaged e il ritorno al codice managed.

Per questo motivo per interrompere il simulatore non ci si è solo affidati alla “Thread.Abort” (chiamata
comunque una volta usciti dal codice), ma è stato necessario modificare il codice unmanaged
permettendo la possibilità di interrompere il ciclo principale.

36
Capitolo 3 - Implementazione

3.4 Implementazione del front-end


Nei capitoli successivi si andrà ad analizzare la struttura della classe Form1, classe principale del front-
end. Per motivi di spazio non si riporta il diagramma della classe (eccessivamente lungo e complesso),
bensì ci si appresta ad analizzare i punti chiave del front-end e la loro realizzazione.

3.4.1 Configurazione del sistema

La configurazione del sistema (intendesi: i valori di default dei campi della form principale) è gestita da
tre metodi della classe Form1:
- createDefaultConfiguration
- loadDefaultConfiguration
- saveDefaultConfiguration

private void createDefaultConfiguration()

Questo metodo crea una configurazione di default per il programma, inizializzando i valori dei
campi di input, le loro descrizioni e il tipo di dato contenuto.

Approfondimento
Per ogni parametro di input esiste un’omonima ArrayList (una struttura simile ad un array, ma
che permette il salvataggio di dati non appartenenti alla stessa tipologia).
Questo metodo istanzia le ArrayList seguendo una struttura di questo tipo (parametro “nrun”):

nrun = new ArrayList { tB_nrun, 100000, "int", "Number of DPD timesteps" };

I campi indicano nell’ordine: il controllo (textbox in genere) associato al parametro (tB_nrun), il


valore di default (100000), il tipo di dato (“int”), e una descrizione testuale del campo che verrà
poi mostrata in barra di stato (“Number of ...”).
Viene inoltre istanziato un array contenente le ArrayList di tutti i parametri, chiamato “paramts”.
Infine, per permettere un accesso più immediato ai valori, si è utilizzato un Dictionary (struttura
che mette in relazione due valori di tipologie definite):

ctrls_paramts = new Dictionary<Control, ArrayList>();

foreach (ArrayList par in paramts)


{
ctrls_paramts.Add((Control)par[0], par);
}
/* now each ArrayList is associated with the control in its first position
* I've created a key for fast accessing the arraylists, the association is
* represented by the dictionary ctrls_paramts. */

Così facendo, per risalire ad un particolare ArrayList a partire da un controllo, basta usare come
il controllo stesso come chiave nel Dictionary “ctrl_paramts”.

private void loadDefaultConfiguration()

Questo metodo carica i valori di default nei campi della form principale, impostando anche le
descrizioni associate (visibili in barra di stato) e il tipo di campo.

37
Capitolo 3 - Implementazione

Approfondimento
Quando la configurazione di default viene modificata (vedi punto 8 del capitolo 2.4.2) viene
creato un file chiamato “default.xml” in una sottocartella del programma chiamata “config”.
Anzitutto viene controllata l’esistenza di tale file: in caso negativo tutti i valori saranno presi dalle
ArrayList di default viste prima, altrimenti parte dei valori verrà presa dal file (valori di default e
descrizione) e parte dalle ArrayList.
Sul file “default.xml” viene salvato tutto tranne il tipo del controllo (che infatti viene caricato
sempre dalle ArrayList). Questo per evitare che venga modificato accidentalmente il file,
introducendo valori che potrebbero interferire col corretto funzionamento del programma.

I valori caricati vengono salvati in una struttura chiamata “DataTable”.


Le DataTable sono strutture tabellari che contengono campi (colonne) e record (righe);
permettono inoltre query di selezione sui record.
La DataTable che conterrà i dati caricati avrà 4 campi: “name”, “defaultVal”, “description” e
“type”. Esempio di istanziamento di una DataTable:
DataTable dataCfg = new DataTable("configuration");
dataCfg.Columns.Add("name");
[...]

A questo punto devo aggiungere i record. Per aggiungere un record devo definire un oggetto
del tipo “DataRow”:
DataRow dr;
foreach (ArrayList par in ctrls_paramts.Values)
{
dr = dataCfg.NewRow();
/* name and type are taken from default array par */
dr["name"] = ((Control)par[0]).Name;
dr["type"] = par[2].ToString();
[...]
Successivamente creo un record per ogni parametro di input (in pratica scorro tutti gli ArrayList
contenuti nel Dictionary creato con la “createDefaultConfiguration”) e riempio i campi “name”
e “type” prendendo i valori dall’ArrayList del parametro.

Precedentemente si era detto che nel caso dell’esistenza di un file di configurazione, parte dei
valori sarebbero stati caricati e presi da quello. Difatti, viene creata una DataTable che
conterrà i valori caricati (chiamata “dataCfg_loaded”) e in seguito viene popolata utilizzando il
metodo “ReadXml”, che permette la lettura di dati da file xml (a patto che tale file sia stato
precedentemente generato con un altro metodo: “WriteXml”):

dataCfg_loaded.ReadXml("config\\default.xml");

Tornando al caricamento dei valori, parte di essi sono stati presi dall’ArrayList del parametro, i
restanti (“defaultVal” e “description”) vengono presi dunque da questa “dataCfg_loaded”
accedendo alla riga di interesse tramite una query di selezione:

dr_loaded = dataCfg_loaded.Select("name='"+((Control)par[0]).Name+"'");
if (dr_loaded.Count() == 1)
{
dr["defaultVal"] = dr_loaded[0]["defaultVal"];
[...]

38
Capitolo 3 - Implementazione

In sostanza si applica il metodo “Select”; il criterio di ricerca è “il campo ‘name’ deve
contenere il nome del controllo associato all’ArrayList corrente” (siamo ancora dentro il ciclo
dove scorrevamo tutti gli ArrayList dei parametri).

Una volta popolata la DataTable restano due cose da fare:


- creare una struttura che visualizzi i valori di default (in modo da poterli modificare):

dGV_configuration.DataSource = dataCfg;

(è stata utilizzata una struttura di tipo“DataGridView” chiamata “dGV_configuration” ed è


stata associata alla DataTable appena popolata)
- aggiornare i controlli della form con i nuovi valori caricati:

foreach (DataRow row in dataCfg.Rows)


{
if ((this.panel4.Controls.Find(row["name"].ToString(), true)).Count() == 1)
{
Control ctrl = this.panel4.Controls[row["name"].ToString()];
ctrl.Text = row["defaultVal"].ToString();
ctrl.Enter += new EventHandler(tB_Enter);
[...]

Dopo aver verificato l’esistenza del controllo tra i controlli del panel dove si trova la form di
input, viene impostato il suo valore (ctrl.Text) e l’evento da eseguire quando si entra nel campo
(ctrl.Enter). L’evento da eseguire sarà una funzione che usa il controllo come chiave nel
Dictionary “ctrls_paramts”, ottiene l’ArrayList del parametro associato al controllo, prende il
campo con la descrizione e lo mostra nella barra di stato del front-end.

private void saveDefaultConfiguration()

Chiamata al momento di salvare le modifiche alle configurazioni di default del programma.


Salva in un file esterno chiamato “default.xml” i nomi dei controlli della form e i rispettivi valori di
input e descrizione.

Approfondimento
I valori di default sono stati creati all’avvio del programma e si trovano, oltre che nelle ArrayList
dei parametri, nella DataGridView “dGV_configuration”.
Per salvare i parametri sul file:
- si va a riprendere la DataTable associata a tale DataGridView
- ne si fa una copia (per non modificare l’originale)
- si rimuove il campo “type” che, come è stato precedentemente detto, non verrà salvato
poiché non modificabile
- si salva su file utilizzando il metodo “WriteXml” della classe DataTable

DataTable data_original = (DataTable)dGV_configuration.DataSource;


DataTable data = data_original.Copy();
data.Columns.Remove("type");
data.WriteXml("config\\default.xml", true);

39
Capitolo 3 - Implementazione

3.4.2 Salvataggio / caricamento dei parametri

Il salvataggio e caricamento dei parametri di input viene effettuato tramite i due metodi:
- saveParamsToXML
- loadParamsToXML

private void SaveParamsToXML(string fileName)

Questo metodo della classe Form1 scorre tutti i controlli presenti nella form di input principale e
ne memorizza il valore (oltre che al nome) su un file esterno di tipo XML a scelta dell’utente.

Approfondimento
Viene creata una DataTable che conterrà i valori, viene popolata scorrendo i controlli della
Panel che contiene la form di input (filtrandoli in base a una convenzione sul nome), infine
viene salvata la DataTable utilizzando il metodo “WriteXml” precedentemente visto.

private bool LoadParamsFromXML(string fileName)

La funzione controlla l’esistenza del file e carica da esso i valori dei campi della form di input.
Nel caso qualcosa non andasse a buon fine (struttura del file xml corrotta, errore in lettura, file
non trovato) restituisce il valore false.
Se i valori sono stati correttamente caricati, vengono aggiornati i controlli.

Approfondimento
I valori vengono caricati in una DataTable mediante il metodo “ReadXml” precedentemente
visto. Sono effettuati controlli sulle eccezioni di tipo “XmlException” (struttura danneggiata) o
“InvalidOperationException” (la struttura dell’oggetto di destinazione non corrisponde a quella
presente nel file xml).
L’aggiornamento dei controlli viene fatto con un ciclo sui record della DataTable appena
popolata. I controlli sono come al solito filtrati in base a convenzioni sul nome (deve iniziare per
“tB_”).

L’utilità del valore del ritorno: serve al metodo chiamante per informare l’utente dell’avvenuto
errore, e offrire la possibilità di caricare comunque i valori di default dell’applciativo al posto di
quelli salvati.

3.4.3 Controllo dei parametri

Il controllo dei parametri immessi nella form di input è compito di due metodi (più un terzo metodo
chiamato all’interno del secondo):
- areParametersOk
- loadParametersFromControls
o setInputFromCtrl

40
Capitolo 3 - Implementazione

public bool areParametersOk()

Effettua una semplice verifica che tutti i controlli della form di input (filtrati opportunamente in
base al nome) non siano vuoti.

private bool loadParametersFromControls()

Carica dai controlli della form di input i valori, controlla la correttezza del tipo e li salva in
particolari strutture dati di tipo Dictionary, che verranno utilizzate successivamente al momento
di passare i parametri alla classe SimulatorDLL.

Approfondimento
Tra le variabili globali della classe Form1 sono state predisposte tre strutture di tipo Dictionary.
Tutte e tre usano come chiave una stringa, tuttavia memorizzano valori di tipo differente:
- Stringa e intero:
Dictionary<string, int> input_i = new Dictionary<string, int>();

- Stringa e double:
Dictionary<string, double> input_d = new Dictionary<string, double>();

- Stringa e stringa:
Dictionary<string, string> input_s = new Dictionary<string, string>();

Il metodo preso in considerazione scorre tutti i controlli della form di input, controlla il tipo
associato ad ogni controllo e aggiunge al Dictionary corrispondente la coppia: (nome del
parametro, valore).
Per ottenere il tipo di un controllo si prende il controllo, lo usa come chiave nel Dictionary
“ctrls_paramts” ottenendo l’ArrayList associato, nell’ArrayList trovato si va quindi a prendere il
tipo di dato memorizzato nel controllo (può essere “int”, “double” o “string”).
La verifica che il tipo del valore presente nel controllo coincida col tipo specificato per tale
controllo viene fatta dal metodo “setInputFromCtrl (nome del parametro,valore,tipo)” che
viene analizzato nel paragrafo successivo.

foreach (Control ctrl in ctrls_paramts.Keys)


{
if (!setInputFromCtrl(ctrl.Name.Substring(3), ctrl.Text,
ctrls_paramts[ctrl][2].ToString()))
{
MessageBox.Show([...]);
return false;
[...]

Alla setInputFromCtrl viene passato dunque:


- nome del parametro (ctrl.Name.Substring(3)) che corrisponde al nome del controllo
privato delle prime tre lettere (le famose “tB_” che servono come filtro nei metodi
precedentemente visti)
- valore del parametro (ctrl.Text), preso dunque dal controllo
- tipo del parametro (ctrls_paramts[ctrl][2].ToString()), contenuto nel terzo campo
dell’ArrayList del parametro, ArrayList ottenuto dal Dictionary “ctrl_paramts” usando il
controllo come chiave.

41
Capitolo 3 - Implementazione

public bool setInputFromCtrl(string name, string value, string type)

Converte la variabile “value” da stringa generica a valore in base al tipo descritto da “type”; in
seguito aggiunge la coppia (“name”, valore_convertito) a uno dei tre Dictionary “input_i”,
“input_d”, “input_s” a seconda del tipo.

Approfondimento
La conversione viene fatta utilizzando i metodi della Classe statica “Convert”. Il controllo sulla
correttezza del tipo viene fatto catturando le eventuali eccezioni sollevate al momento della
conversione:
try
{
switch (type)
{
case "int":
input_i.Add(name,Convert.ToInt32(value));
break;
case "double":
input_d.Add(name, Convert.ToDouble(value));
break;
case "string":
input_s.Add(name, value);
break;
default:
return false;
}

}
catch (FormatException)
{
MessageBox.Show([...]);
return false;
[...]

3.4.4 Monitoring e visualizzazione su grafico

I metodi che si occupano del controllo del file di monitoring e della visualizzazione su grafico sono:
- initializeGraph
- updateGraph
Prima di passare all’analisi di questi metodi è bene introdurre la libreria utilizzata per la visualizzazione di
valori sottoforma di grafico: la libreria ZedGraph.

Libreria ZedGraph
ZedGraph (http://zedgraph.org/) è un set di classi scritte in C# per la creazione di grafici 2D a partire da
diverse tipologie di valori.
E’ stata scelta poiché essendo scritta in C# è utilizzabile anche in ambiente Linux, difatti risulta
nell’elenco delle librerie supportate e consigliate da Mono (http://www.mono-project.com/Libraries).
Il modulo “initializeGraph” è stato sviluppando a partire da un modulo già esistente nel progetto di
demo distribuito con la libreria. Pertanto per quanto riguarda l’utilizzo si rimanda alla documentazione
sul sito ufficiale.

42
Capitolo 3 - Implementazione

private void initializeGraph()

Inizializza i due grafici presenti nella schermata della simulazione (imposta nomi degli assi, colori,
tipologie di curve e altri parametri strettamente legati alla visualizzazione dei grafici).
Per i motivi spiegati nel paragrafo precedente non ne viene approfondita l’implementazione.

private void updateGraph()

Questo è il metodo che si occupa dell’aggiornamento vero e proprio dei grafici prendendo i
valori dal file di monitoring “monitor.dat” aggiornato durante la simulazione.

Approfondimento (il controllo Timer e la classe Thread)


L’aggiornamento del grafico è un processo che si ripete a determinati intervalli di tempo (ogni
qualvolta venga modificato il file “monitor.dat”.
Un’alternativa all’utilizzo dei thread (come è stato fatto per la simulazione – vedi capitolo 3.3.3)
è costituita dall’utilizzo del controllo Timer.
Il controllo Timer difatti appartiene al namespace “System.Windows.Forms” ed è ottimizzato per
lavorare nelle applicazioni Windows Forms (come riportato sulla documentazione MSDN:
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx). La classe Thread invece, non

è nata per la gestione dei controlli nelle Windows Form, infatti è bene ricordare come non sia
possibile modificare le proprietà di un controllo creato da un thread, da parte di un altro thread
(viene generata un eccezione del tipo “CrossThreadException”).

Approfondimento
Il metodo “updateGraph” è associato a un Timer chiamato “timer_updateGph”; tale Timer,
avviato appena finita la fase di inizializzazione da parte del simulatore, genera l’evento
updateGraph ad intervalli di tempo definiti.
L’intervallo di tempo con il quale viene controllato il file di monitoring (e quindi generato il
grafico) non è fisso, ma è calcolato in base al parametro “nprint” impostato nella simulazione.
In seguito a diversi test effettuati su un PC relativamente potente (Intel Core 2 Duo P8600 / 4GB
di RAM) si è giunti a una stima di esecuzione di 10 timesteps/sec (quindi 1 timestep corrisponde
a 100ms facendo il rapporto).
Per questo motivo è stato settato l’intervallo del “timer_updateGph” a (100 * nprint) ms.

timer_updateGph.Interval = Convert.ToInt32(tB_nprint.Text) * 100;

Tornando al metodo, viene inizialmente controllata la presenza del file di monitoring (in caso
negativo si ferma il Timer e si esce con un messaggio d’errore); in seguito si controlla la
lunghezza del file e se ne memorizza il valore. Se tra due letture il valore è cambiato allora si
legge l’ultima riga e si aggiorna il grafico:

FileStream fs = File.Open("monitor.dat", FileMode.Open, FileAccess.Read,


FileShare.ReadWrite);
StreamReader sr = new StreamReader(fs);
sr.BaseStream.Position = fs.Length - 66;
line = sr.ReadToEnd();
[...]

L’ultima riga è sempre a 66 bytes dalla fine, dal momento che le righe han lunghezza costante.
Importante il parametro FileShare.ReadWrite poiché il file è aperto anche dal simulatore.

43
Capitolo 3 - Implementazione

Nel caso non si aprisse il file in condivisione di lettura e scrittura si andrebbe incontro ad un
errore di accesso concorrenziale al file da parte della libreria del simulatore.

Dalla riga letta vengono estratti i valori con una semplice operazione di parsing; in seguito tali
valori sono convertiti in formato double, utilizzando i metodi della classe Convert, e vengono
passati ai metodi della libreria “ZedGraph” per l’aggiornamento dei grafici.

3.4.5 Interazione con la simulazione

I metodi per l’interazione con la simulazione sono sostanzialmente due:


- simulStart
- simulStop
associati ai corrispondenti pulsanti e voci di menu.
Oltre a questi due metodi è importante citare i due controlli di tipo Timer che hanno il compito di
controllare l’avvenuta fine dell’inizializzazione e l’avvenuta interruzione della simulazione,
rispettivamente:
- timer_checkinit
- timer_checkstop
ai quali sono associati i rispettivi eventi da eseguire (secondo gli intervalli stabiliti).

private void simulStart()

Istanzia un oggetto della classe SimulatorDLL (vedi capitolo 3.3.2), inizializza i grafici, passa i
parametri caricati dalla form di input al simulatore, infine avvia la simulazione e il
“timer_checkinit” che si occuperà di controllare la fine dell’inizializzazione.

Approfondimento
Il passaggio dei parametri avviene in due fasi:
1) vengono caricati i parametri dai controlli della form di input e vengono salvati nei
Dictionary predisposti “input_i”, “input_d” e “input_s” utilizzando il metodo
“loadParametersFromControls” (vedi capitolo 3.4.3)
2) viene chiamato il metodo “setSimInput” della classe SimulatorDLL passando i valori
contenuti nei tre Dictionary:

dpd.setSimInput(input_d["L"],[...],input_i["nrun"],[...],input_s["cnfile"])

(esempio di passaggio di input, valori omessi per questioni di spazio)

private void timer_checkinit_Tick(object sender, EventArgs e)

Metodo chiamato ogni 6 secondi (si consideri che la fase di inizializzazione a seconda dei valori
di input può durare da una decina di secondi a diversi minuti in media).
Si occupa di controllare l’avvenuta fine della fase di inizializzazione della simulazione servendosi
del metodo “isSimInitialized” della classe SimulatorDLL.

44
Capitolo 3 - Implementazione

Una volta verificatasi tale condizione, ferma il timer associato (“timer_checkinit”) e avvia i due
timer relativi al controllo della fine simulazione (“timer_checkstop”) e all’aggiornamento dei
grafici di monitoring (“timer_updateGph”).

private void simulStop()

Metodo che si occupa di interrompere la simulazione; in sostanza chiama il metodo “stop”


della classe SimulatorDLL. Oltre a chiamare tale metodo cambia l’intervallo del timer
“timer_checkstop” impostandolo sul valore di 2 secondi.
Il cambio di intervallo è dovuto al fatto che normalmente non si sa quando può interrompersi la
simulazione (quindi è necessario un controllo su tempi relativamente lunghi), una volta
chiamata la simulStop, invece, si sa che la simulazione verrà interrotta nel giro di pochi secondi,
per cui è necessario ridurre l’intervallo di controllo.

private void timer_checkstop_Tick(object sender, EventArgs e)

Metodo chiamato ogni 120 secondi (si ricorda che una simulazione può durare minuti, ma
anche ore o giorni) per non pesare sul carico di lavoro della CPU.
Questo metodo controlla l’effettiva interruzione della simulazione sfruttando il metodo
“isSimStopped” della classe SimulatorDLL.
Una volta verificatasi tale condizione ferma il timer associato (“timer_checkstop”) e il timer per
l’aggiornamento dei grafici di monitoring (“timer_updateGph”).
Inoltre, ricava il codice d’errore restituito dalla simulazione (tramite una chiamata al metodo
“getSimErrorCode” sempre della classe SimulatorDLL) e prevede due situazioni di output in base
al fatto che il simulatore sia stato interrotto manualmente o sia stato terminato in seguito alla
fine dell’algoritmo di simulazione.

3.5 Implementazione interfaccia grafica

3.5.1 Struttura

La struttura scelta per l’implementazione dell’interfaccia consiste in una semplice applicazione di tipo
SDI (Single Document Interface); una finestra singola, contenente però più controlli di tipo Panel; in
sostanza ogni controllo di tipo Panel è a sua volta un contenitore di altri controlli.
Ho 3 Panel principali (vedi figura 3.4):
- uno per la form di immissione input, che costituisce la schermata iniziale
- uno per la configurazione dei parametri di default del programma
- uno per lo stato della simulazione e per i grafici di monitoring
La scelta della struttura ricalca le funzionalità dell’applicativo:
- introdurre input
- configurare i parametri dell’interfaccia
- interagire con la simulazione

45
Capitolo 3 - Implementazione

Figura 3.4 - Struttura dell'interfaccia grafica

3.5.2 Usabilità e controlli

L’interfaccia utente è un fattore fondamentale al giorno d’oggi, essa deve sostanzialmente adattarsi
all’utente e non viceversa. E’ importante tenere conto dei seguenti parametri al momento della
progettazione di un’interfaccia utente:
- deve adattarsi a diverse tipologie di utenti: sia principianti che esperti. Ciò si traduce in
informazioni più dettagliate e suggerimenti, ma anche in tasti di scelta rapida e pochi
messaggi di conferma (solo se necessari).
- deve prevenire l’immissione di input errato, effettuando controlli sui campi e informando
l’utente sulle modalità di compilazione di una form

Nel progetto che è stato realizzato ciò si traduce nelle seguenti scelte:
- presenza di un menu (che offre in maniera strutturata tutte le funzionalità disponibili)
- presenza di una barra di stato (che permette di mostrare all’utente messaggi utili senza però
utilizzare
- finestre di tipo MessageBox che richiedono un’interazione)
- presenza di descrizione per ogni controllo (per aiutare l’utente principiante nell’utilizzo
dell’applicativo)
- presenza di tasti di scelta rapida sui menu e sui pulsanti (per favorire l’utilizzo da parte di utenti
esperti)

46
Capitolo 3 - Implementazione

3.6 Approfondimenti e ulteriori modifiche

3.6.1 Utilizzo in ambiente Windows e StackOverflow

Prima di terminare il capitolo riguardante l’implementazione è bene mettere in luce una modifica
importante da apportare all’applicazione per quanto riguarda la gestione dello stack.
Il problema di fondo nasce dall’utilizzo del simulatore come libreria dinamica. Esso infatti, non essendo
nato per essere utilizzato all’interno di una libreria, è strutturato in modo da gestire lo stack a
disposizione unicamente per se stesso. Al momento, invece, della chiamata da parte di
un’applicazione esterna, lo stack a disposizione per il front-end e la libreria si esaurisce generando
un’eccezione di StackOverflow.

Modifica dello dimensioni dello stack riservato


In ambiente Windows le informazioni sulle dimensioni dello stack sono contenute all’interno dei file
eseguibili stessi; per tale motivo è possibile tramite opportuni strumenti risalire a tali dimensioni.
Uno di questi è rappresentato dal Microsoft COFF Binary File Dumper (“dumpbin.exe”) che permette di
ottenere informazioni su particolari file binari a 32-bit. Tramite questo tool si è riusciti a risalire alla
dimensione dello stack destinata al progetto:

100000 size of stack reserve

Il valore è in esadecimale, in decimale corrisponde a 1.048.576 (byte), cioè 1MB riservato allo stack.
Dopo un’attenta ricerca si è giunti ad una soluzione per modificare la dimensione dello stack riservato
all’applicativo, utilizzando il tool Microsoft Binary File Editor (“editbin.exe”).
Dopo diversi test, è stato possibile valutare un valore accettabile per la dimensione dello stack che si
assesta attorno ai 5MB.

NOTA: L’istruzione per la modifica dello stack è la seguente:

editbin /stack:nuova_dimensione_dello_stack_in_byte

3.6.2 Compilazione in ambiente Linux e relative modifiche

Requisiti di sistema
Il testing verrà effettuato su un sistema operativo Linux: la distribuzione OpenSUSE 11.0 con ambiente
Mono 2.2. Si preannuncia già che per motivi che verranno approfonditi nei prossimi paragrafi è
necessaria una versione della libreria “libgfortran” >= 4.4 (quindi una versione del compilatore “gcc”
superiore alla 4.3)

Compilazione della libreria


Il codice sorgente viene ricompilato in ambiente Linux tramite il compilatore gfortran.
E’ importante che il compilatore “gcc” (al quale si appoggia il programma gfortran) sia aggiornato ad
una versione superiore alle 4.3. Questo poiché le versione precedenti contengono un bug legato alla
scrittura su file (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19363).

47
Capitolo 3 - Implementazione

Il sorgente viene compilato in una libreria condivisa (quindi con estensione .so – Shared Object):

gfortran –shared –fPIC –o libsimulatordpd.so nome_del_file_sorgente

A questo punto non basta collocare la libreria nella cartella dell’applicativo. Difatti, durante il testing
l’applicativo non riconosceva la libreria generando una DllNotFoundException.
Dalla documentazione di Mono si è giunti a una soluzione:
- copiare la libreria nella cartella “/usr/local/lib”
- introdurre se non già presente tale percorso nel file “/etc/ld.so.conf”
- avviare il programma “ldconfig” aggiornando la cache delle librerie condivise
(per ulteriori informazioni su ldconfig: http://linux.die.net/man/8/ldconfig)

Modifiche al front-end
Il front-end richiede pochissime modifiche (come da obiettivo preposto); è necessario:
- modificare il riferimento alla libreria nell’istruzione “DllImport” mettendo il nuovo nome
- modificare i nomi delle subroutine interfacciate (poiché il compilatore gfortran non supporta la
direttiva “alias” – vedi capitolo 3.2.1)

NOTA: in ambiente Linux non si ha a disposizione il programma “dumpbin.exe” (vedi capitolo 3.2.1),
tuttavia per ottenere il nome delle subroutine esportate dalla libreria è sufficiente utilizzare l’applicativo
“objdump”:

objdump -T libsimulatordpd.so

48
Capitolo 4 - Interfaccia

Capitolo 4

Interfaccia

Capitolo dedicato all’interfaccia del sistema: vengono illustrate le funzionalità dell’applicativo


attraverso un tipico esempio di utilizzo.
Seguono poi delle considerazioni sulla portabilità, supportate da una breve descrizione della fase di
testing in ambiente Linux.

4.1 Installazione / Configurazione


L’applicazione viene distribuita senza necessità di installazione. Il progetto in sé consiste di tre files
fondamentali:
- Il front-end: “ReactiveDPDSimulator.exe”
- la libreria del simulatore: “dpdsimulator.dll”
- la libreria per la gestione dei grafici: “ZedGraph.dll”
(NOTA: le librerie devono trovarsi nella stessa cartella del front-end)
Il progetto inoltre presenta come requisiti di sistema:
- ambiente Windows XP / Vista
- Microsoft .NET Framework 3.5 SP1 installato

4.2 Esempio di utilizzo


L’applicazione una volta avviata presenta una schermata principale contenente un menu con tutte le
funzionalità in alto, la form di input dei parametri, e un menu di navigazione rapida sulla sinistra per
passare dalla fase di input alla fase di simulazione (vedi figura 4.1)

49
Capitolo 4 - Interfaccia

4.2.1 Immissione dell’input

La form risulta già compilata (fatta eccezione per il nome del file di configurazione) con i valori di
default previsti all’interno del programma (ricavati dalle specifiche – vedi capitolo 2.4.1)

Figura 4.1 - Schermata principale e form di input

Nel caso in cui si scelga di ripristinare una precedente simulazione, verrà abilitato il pulsante accanto al
campo “Configurational file” che permetterà di scegliere un file di configurazione generato in una
simulazione precedente (vedi figura 4.2)

Figura 4.2 - Caricamento file di configurazione del simulatore

50
Capitolo 4 - Interfaccia

E’ possibile aprire anche file contenuti in cartelle diverse da quella dell’applicazione principale, il
programma stesso si occuperà di verificare la cartella ed eventualmente di creare una copia del file
scelto nella cartella principale (ciò è necessario poiché il simulatore è nato per funzionare con un file di
configurazione presente nella propria cartella).

4.2.2 Salvataggio/caricamento dei parametri

Nel caso si voglia salvare l’input immesso nella form è sufficiente premere il tasto “Save” o scegliere dal
menu “Parameters -> Save”, la prima volta verrà chiesto il nome del file su cui salvare, successivamente
i salvataggi avverranno sul file specificato la prima volta, senza dover ripeterne il nome.
Nel caso invece si vogliano salvare i parametri su un nuovo file è sufficiente scegliere dal menu
“Parameters -> Save As...” (vedi figura 4.3)

Figura 4.3 - Dettaglio del menu "Parameters"

Per caricare dei parametri precedentemente salvati è sufficiente utilizzare il pulsante “Load” presente in
fondo alla form di input, o in alternativa selezionare dal menu “Parameters -> Load”.
Nel caso in cui il file XML sia corrotto o sia stato manualmente modificato in maniera errata verrà
comunicato l’errore richiedendo se sia necessario caricare i valori di default del programma (vedi
figura 4.4)

Figura 4.4 - Messaggio d'avvertimento in caso di file xml corrotto

51
Capitolo 4 - Interfaccia

4.2.3 Configurazione del programma

Se invece di salvare e caricare file contenenti i parametri di input si è soliti utilizzare spesso un’unica
configurazione di input, potrebbe risultare conveniente modificare la configurazione di default del
programma (i valori caricati all’avvio per intendersi).

Per fare ciò è sufficiente selezionare dal menu la voce “GUI Settings”, si accede a una sezione dove è
possibile modificare i valori di default dei campi e la loro descrizione (vedi figura 4.5); in seguito è
possibile scegliere se salvare (pulsante “Save”) o semplicemente tornare alla schermata principale
senza effettuare modifiche (pulsante “Back”).

NOTA: Le colonne “name” e “type” sono in sola lettura, questo per evitare che un utente possa
inavvertitamente modificare valori di vitale importanza per il corretto funzionamento dell’applicazione.
Tali valori non possono essere modificati, in quanto strettamente legati alla struttura del front-end.

Figura 4.6 - Schermata di configurazione del programma

52
Capitolo 4 - Interfaccia

4.2.4 Avvio della simulazione

Una volta completato l’input della form principale si può passare alla fase di simulazione selezionando
la voce “2. Go to simulation” nel menu di navigazione rapida a sinistra.
Se l’input immesso è incorretto viene comunicato un messaggio d’errore e si viene riportati alla
schermata di input. Vengono inoltre evidenziati i campi con valori incorretti. (vedi figura 4.7)

Figura 4.7 - gestione di input errato tramite messaggio ed evidenziazione dei campi

In caso contrario è possibile accedere a una nuova schermata contenente lo stato della simulazione,
per il momento vuoto, e i grafici di monitoring, ancora da inizializzare.
A questo punto è sufficiente avviare la simulazione utilizzando il pulsante “start” o selezionando dal
menu “Simulation -> Start”; notare come il pulsante “stop” sia disabilitato: verrà abilitato solo una volta
finita la fase di inizializzazione.
A questo punto i grafici vengono configurati e viene comunicato l’avvio della simulazione e della fase
di inizializzazione (che può durare in media diversi minuti), richiedendo la conferma da parte dell’utente
(vedi figura 4.8)

Figura 4.8 - schermata di simulazione e messaggio di avvio inizializzazione

53
Capitolo 4 - Interfaccia

Una volta finita la fase di inizializzazione è possibile stoppare la simulazione in qualunque momento
tramite il pulsante “stop”. Come si può notare è possibile vedere lo stato della simulazione nella sezione
“Status”, mentre è possibile seguire l’andamento in tempo reale dei valori di monitoring nei grafici
sottostanti (vedi figura 4.9).

Figura 4.9 - Visualizzazione stato della simulazione e monitoring dei parametri

Infine, si ha a disposizione il log/result della simulazione nel file generato nella cartella principale,
chiamato “logresult.txt”; esso conterrà dunque i messaggi di output avvenuti durante la simulazione,
nonché, i risultati finali a fine simulazione.

4.3 Testing in ambiente Linux


Il progetto è stato testato su una distribuzione openSUSE 11.0, con già installato Mono (versione 2.2).
L’interfaccia in ambiente Mono è sufficientemente simile a quella nativa di Windows (vedi figure 4.10 e
4.11), ciò è dovuto al supporto di Mono alla compatibilità con la classe “System.Windows.Form”.

Figura 4.10 - Schermata principale (ambiente Mono)

54
Capitolo 4 - Interfaccia

Figura 4.11 - Visualizzazione stato simulazione (ambiente Mono)

L’unico problema rimasto è rappresentato dall’illeggibilità del file di log; ciò è molto probabilmente un
errore legato al compilatore gfortran 4.4 e alla scrittura su file in particolari contesti (c’era già stato un
bug nelle precedenti versioni, come visto nel capitolo 3.6.2).

55
Capitolo 5 - Conclusioni

Capitolo 5

Conclusioni

Capitolo conclusivo del documento nel quale si cercherà di fare il punto della situazione attuale e
valutare eventuali prospettive e sviluppi futuri; si prenderanno inoltre in considerazione gli obiettivi iniziali
per stilare un’analisi qualitativa su ciò che è stato realizzato.
Seguiranno, infine, le conclusioni personali da parte dell’autore del documento.

Il sistema risultato di questo processo di analisi e sviluppo rappresenta una soluzione soddisfacente gli
obiettivi funzionali preposti. Il risultato, infatti, consiste in un front-end grafico interfacciato, secondo più
prospettive, con la soluzione di partenza.
Si può affermare di aver soddisfatto in sostanza i requisiti di usabilità che rendevano per l’appunto il
progetto originario incompleto. Si è lavorato non solo sull’interfaccia grafica, ma sui punti di debolezza
intrinseci al simulatore stesso; le modifiche apportate sono il frutto non solo di necessità meramente
tecniche di interfacciamento, ma anche di un’attenta analisi sull’usabilità dell’applicativo esistente.
La nuova interfaccia, inoltre, è stata progettata da un lato per l’adattabilità al motore di simulazione,
dall’altro per fornire le funzionalità utili ai futuri utilizzatori nell’ambito del contesto universitario.

Il front-end realizzato è implementato sul framework Microsoft .NET 3.5 ed è composto di 1007 righe di
codice in linguaggio C#. Il core del sistema è costituito dal simulatore, rimasto nel linguaggio Fortran90
e modificato in maniera mirata; esso è implementato in ambiente nativo e si interfaccia al front-end
sotto forma di libreria dinamica. Sono state introdotte 7 subroutine e funzioni per un totale di 136 righe
aggiunte al progetto iniziale (senza considerare le modifiche apportate).
Il sistema, inoltre, è stato testato in ambiente Linux per soddisfare il requisito (non vincolante, ma utile ai
fini del progetto in questione) di portabilità. Il risultato si è rilevato positivo: il codice richiede un numero
considerevolmente minimo di modifiche, inoltre le funzionalità sono quasi tutte rispettate (ad eccezione
del file di log/result che per via di un bug non risulta leggibile).

56
Capitolo 5 - Conclusioni

Il sistema attualmente è in fase di testing all’esterno dell’Università. Prima del suo effettivo utilizzo
nell’ambiente di destinazione sarà necessario però definire gli sviluppi futuri del progetto e, cosa di
maggiore importanza, le tempistiche associate.

Sviluppi futuri
Sicuramente i punti sui quali si intende lavorare in previsione di scenari futuri sono:
- porting del simulatore all’interno del framework
- aggiunta di nuovi parametri di gestione della simulazione
- portabilità completa in ambiente Linux
Il primo punto è relativo alla possibilità di compilare il simulatore internamente al framework .NET
(tramite la soluzione commerciale Lahey Visual Fortran). Le motivazioni che muovono in questa
direzione riguardano vantaggi in campo di sicurezza (tutto il codice diventa managed ed eseguito
nell’ambiente virtuale messo a disposizione) e nel campo delle prestazioni (il codice compilato in tal
modo è ottimizzato per l’esecuzione all’interno del framework). Questa scelta era già stata affrontata
nelle fasi di analisi e implementazione, tuttavia necessita dell’assenso da parte dello sviluppatore del
codice originale.
Il secondo punto riguarda la possibilità di gestire ulteriori valori di input al di fuori di quelli standard
richiesti nei requisiti; questo può essere utile per utilizzatori più esperti che vogliono avere a disposizione
più parametri sui quali intervenire. E’ richiesta tuttavia una modifica strutturale al programma che
potrebbe richiedere tempi di realizzazione significativi.
Il terzo punto prende in considerazione la risoluzione delle problematiche presenti allo stato attuale
nella fase di porting (il bug nella generazione del file di log) e prevede un’ulteriore fase di testing per
verificare l’effettivo funzionamento in ambiente Mono. I tempi previsti per questo scenario sono da
definirsi.

Considerazioni finali
Il processo di sviluppo del sistema in esame ha visto il susseguirsi delle tipiche fasi studiate nell’ambito
dell’Ingegneria del Software. L’applicazione concreta dei metodi di studio ed analisi affrontati nel
contesto di molte materie universitarie risulta una risorsa quanto mai preziosa per un laureato in
Ingegneria. Da un punto di vista strettamente personale si prende in grande considerazione non tanto
la realizzazione in sé del progetto, che comunque richiede tempo e buona dose di impegno, quanto
piuttosto ciò che vi è dietro, ossia l’analisi delle problematiche, la ricerca di soluzioni operative, lo studio
del contesto e delle tecnologie con le quali si lavora. Tutto ciò, difatti, porta al consolidarsi di una
metodologia di lavoro, risultando dunque un’esperienza basilare in previsione di un futuro percorso di
miglioramento professionale.
E’ per questo motivo che si ritiene il documento qui presente non solo un’approfondita
documentazione del lavoro fatto, ma anche il frutto di riflessioni, ricerca e studio riguardo
problematiche sempre più diffuse quali l’interfacciamento tra applicativi in ambienti eterogenei, e la
portabilità su piattaforme diverse.

57
Bibliografia

Bibliografia

Simulazione molecolare – capitoli 1 e 2.1


Progetto europeo “Multipro”
http://www.multipro-f6.eu/

Modellazione multiscala per sistemi nanocompositi di interesse industriale.


Maurizio Fermeglia, S. Pricl, Università di Trieste – 2006

Analisi e specifica dei requisiti – capitoli 2.3, 2.4


Ingegneria dei requisiti, Stefania Gnesi, ISTI-CNR, Pisa
http://fmt.isti.cnr.it/~gnesi/matdid/requisiti.pdf

Il progetto Mono – capitolo 2.5


Start - Mono
http://mono-project.com/Start

Articoli vari su Mono


http://www.keepintech.it/blog/?cat=3

Linux.com :: Why Mono is significant


http://www.linux.com/feature/37502

Main Page - MonoDevelop


http://monodevelop.com/Main_Page

Novell's Mono Project Extends Microsoft .NET Framework to Linux


http://www.novell.com/news/press/novells_mono_project_extends_microsoft__net_framework_to_linux

.NET Framework architettura – capitolo 3.1


.NET Framework / C# Tutorial a cura di Carlo Becchi
http://www.deathlord.it/pro/sl/ricerca/tutorial.net/

Common Intermediate Language « Robert’s WebLog


http://robertsundstrom.wordpress.com/2008/07/21/common-intermediate-language/

NationMaster - Encyclopedia: Common Intermediate Language


http://www.nationmaster.com/encyclopedia/Common-Intermediate-Language

La sicurezza arriva da .NET Framework


http://technet.microsoft.com/it-it/library/cc677304.aspx

Direttive per la compilazione di una libreria – capitolo 3.2.1


ATTRIBUTES Directive
http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0586.htm

ATTRIBUTES Properties and Calling Conventions


http://www.ncsa.uiuc.edu/UserInfo/Resources/Software/Intel/Compilers/8.1/f_ug1/pgwadjat.htm

58
Bibliografia

Variabili e input/output in Fortran – capitoli 3.2.2, 3.2.3


Fortran – Data Types and Declarations
http://www.obliquity.com/computer/fortran/datatype.html

FORTRAN File Handling


http://www.livephysics.com/computational-physics/fortran/fortran-file-handling.html

Fortran Format (read and write)


http://www.cs.mtu.edu/~shene/COURSES/cs201/NOTES/chap05/format.html

Creating Files with the OPEN Statement


http://docs.hp.com/cgi-bin/doc3k/B3150190022.12120/22

Utilizzo della direttiva ‘stop’ – capitolo 3.2.4


Using a Fortan DLL in VB that has a STOP command - Intel® Software Network
http://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/38715/

Platform Invoke (P/Invoke) – capitolo 3.3.1


DllImport - FORTRAN 77 and C# Combined
http://3dohio.com/?p=8

dotNetHell.it - Come sfruttare le funzioni di una DLL unmanaged esterna creata in C/C++
http://www.dotnethell.it/articles/UnmanagedDLL.aspx

System.Runtime.InteropServices - Documentazione Microsoft


http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.aspx

Platform Invocation Services in .NET Framework


http://www.c-
sharpcorner.com/UploadFile/dahuja/PInvokeServices11092005062837AM/PInvokeServices.aspx

C Sharp Declaring The Exported DLL Function Tutorials


http://www.brainbell.com/tutors/C_Sharp/Declaring_the_Exported_DLL_Function.htm

CodeProject: Essential P/Invoke. Free source code and programming help


http://www.codeproject.com/KB/cs/essentialpinvoke.aspx

Platform Invoke Tutorial (C#) - Documentazione Microsoft


http://msdn.microsoft.com/en-us/library/aa288468.aspx

Passaggio di parametri – capitolo 3.3.3


Using C and C++ with Fortran
http://www.math.utah.edu/software/c-with-fortran.html

Fortran and C/C++ Mixed Programming


http://www.physiology.wisc.edu/comp/docs/notes/not017.html

Tutorial: Using C/C++ and Fortran together


http://www.yolinux.com/TUTORIALS/LinuxTutorialMixingFortranAndC.html

Dr. Dobb's | C++, Fortran, & Shared Libraries


http://www.ddj.com/cpp/184401748

Calling Other Languages (Interfacing)


http://docs.hp.com/en/B3901-90002/ch05s10.html

59
Bibliografia

Multithreading – capitolo 3.3.3


Threading in C#
http://www.albahari.com/threading/

Utilizzo del threading (C#)


http://msdn.microsoft.com/it-it/library/5xt1dysy(VS.80).aspx

Using Abort(object) : Thread Abort « Thread « C# / C Sharp


http://www.java2s.com/Code/CSharp/Thread/UsingAbortobject.htm

Introduction to Multithreading in C#
http://www.c-
sharpcorner.com/UploadFile/mgold/MultithreadingIntro10062005000439AM/MultithreadingIntro.aspx?Ar
ticleID=920ecafc-e83b-4a9c-a64d-0b39ad885705

C# - Strutture dati, XML ed eccezioni – capitolo 3.4


Hello, C#—1.16 The Hashtable Container at C# Online.NET (CSharp-Online.NET)
http://en.csharp-online.net/Hello,_CSharp%E2%80%941.16_The_Hashtable_Container

Working with Collections in C#: ASP Alliance


http://aspalliance.com/854

kirupa.com - Using a Dictionary (Hashtable) in .NET - Page 1


http://www.kirupa.com/net/dictionary_hashtable.htm

dotNetHell.it - Il DOM XML


http://www.dotnethell.it/articles/DOMXML.aspx

CodeProject: Exception Handling Best Practices in .NET. Free source code and programming help
http://www.codeproject.com/KB/architecture/exceptionbestpractices.aspx

C# - visualizzazione di grafici – capitolo 3.4.4


Open Source Charting & Reporting Tools in C#
http://csharp-source.net/open-source/charting-and-reporting

CodeProject: A flexible charting library for .NET. Free source code and programming help
http://www.codeproject.com/KB/graphics/zedgraph.aspx

Problemi con lo stack in ambiente Windows – capitolo 3.6.1


Stack OverflowException
http://forums.silverfrost.com/viewtopic.php?p=602&sid=7573960b50cf274b8529223cc264d7f2

Fortran, C# and a very large Stack requirement


http://m1kes.blogspot.com/2005/08/fortran-c-and-very-large-stack.html

Stack Overflow Problems


http://www.cs.nyu.edu/exact/core/doc/stackOverflow.txt

Ambiente Linux – Configurazione delle librerie, compilazione in gfortran – capitolo 3.6.2


Librerie statiche e dinamiche in Linux CPP
http://www.bo.cnr.it/corsi-di-informatica/corsoCstandard/Lezioni/37LinuxLibraries.html

Bug 19363 - List directed write of Infinity and NaN has regressed (gfortran)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19363

DllNotFoundException - Mono
http://www.mono-project.com/DllNotFoundException

60
Ringraziamenti

Ringraziamenti
...alla mia famiglia in particolare:
...a mio padre,
per la fiducia riposta in me e perché
mi sta insegnando ad affrontare tutto senza paure nella vita
...a mia madre,
perché mi ha sempre sostenuto in questi ultimi anni,
per la sua pazienza e importanza
...a mia sorella.

...al mio relatore, il prof. Maurizio Fermeglia,


per il sostegno e le motivazioni continue, perché mi ha guidato fino a
questo traguardo, che altro non è che un punto di partenza per me.

...ai miei parenti, ai miei zii.


...a Claudio,
perché vivere in appartamento insieme mi ha ridato l’energia necessaria.

...ai miei amici, in particolare:


...a Stefano,
per i nostri momenti positivi e negativi, per i suoi consigli e il suo aiuto.

...a Luca

...a Carlo e Max,


perché da quando li ho conosciuti la vita a Trieste è cambiata.

...a coloro che, sebbene di passaggio in questi anni,


hanno lasciato un segno indelebile importante per il mio cammino.

...a tutte le persone che mi hanno sostenuto e continuano a farlo.

Grazie.
Filippo

61

Potrebbero piacerti anche