{*********************************************************************}
{            Pietro Mele  -  matr. 603805  -  Ing. Informatica        }
{*********************************************************************}

{ Data di inizio:  7/1992  }
{ Data di fine  :  6/1994  }


Program CFD(input,output);    {**  Computational Fluid Dynamics  **}
                              {**  Versione 1.0  **}

uses CRT,GRAPH;


CONST  maxVert=100;          { massimo numero di vertici del modello }
       maxElem=600;          { massimo numero di elementi }
       maxNodi=3*maxElem;    { massimo numero di nodi }
       noZ=0.01;             { evita l'annullamento dei denominatori }
       data=6.1994;          { data terminazione del programma }


TYPE  coord = record       {** coordinate cartesiane **}
           x,y :real;
           end;

TYPE  elem = record     {** dati di un elemento di spazio **}
           d     :real; { densit… }
           vx,vy :real; { componenti della velocit… V }
           U     :real; { potenziale }
           cx,cy :real; { centro dell'elemento }

           p :array[1..4] of integer; { indirizzi dei nodi dell'elemento }
           e :array[1..4] of integer; { indirizzi degli elementi vicini }
           end;

TYPE  punti = record       {** nodo (=vertice di un elemento) **}
            x,y :real;     { coordinate }
            c :integer;    { 0=punto libero; 1=punto sul profilo; 2=punto fisso }
            end;


VAR  nomeModello,nomeSimulaz :string;         { nomi files }
     modello :array[1..maxVert] of coord;     { modello del profilo }
     nVert :integer;                          { numero di vertici nel modello }
     centroMod :coord;                        { centro del modello }

     simMode :integer;   { modo simulazione: 0=potenziale; 1=Eulero }
     Dat :array[0..maxElem] of elem;       { modello del fluido }
     nodo :array[0..maxNodi] of punti;     { lista dei nodi }
     nDat,nNodi :integer;
     nLivelli :integer;        { numero di livelli }
     nPunti :integer;          { numero di punti su ogni livello }
     scala :real;          { scala per costruire i punti circostanti }
     incrPunti :char;      { flag per incrementare i punti (s/n) }
     newFile :boolean;
     noData :boolean;      { =True se non ci sono dati per l'output }

     dT :real;                     { quanto di tempo, in sec }
     tempo :real;                  { tempo trascorso, in sec }
     scalaDis :real;               { scala del disegno (metri/pixel) }
     vel,angAtt :real;             { velocita' / angolo d'attacco }
     xVel,yVel :real;              { componenti di vel }
     densIniz :real;               { densita' dell'aria }
     Uiniz :real;                  { potenziale iniziale }
     Vmax,Dmax,Umax :real;         { valori massimi e minimi assunti da V,D e U }
     Vmin,Dmin,Umin :real;
     k1P,k2P :real;                { costanti per l'eq. di stato }

     { dati x grafica }
     zoom :real;
     i,maxColors :integer;
     Mx,My :integer;  {dimensioni dello schermo}
     s :string;
     gOpz0,gOpz1,gOpz2,gOpz3,gOpz4,gOpz5,gOpz6,gOpz7,gOpz8 :boolean;  { flags x output grafico }
     lungVettore :integer;  { lunghezza max. in pixel del vettore velocit… }
     deltaS :integer;       { distanza tra due vettori velocit… }
     passoLinee :integer; { passo delle linee di flusso }
     kLinee :integer;     { lunghezza max. di un elemento di linea di flusso }

{*********************************************************************}
{ Procedure   t                   pausa
              apriSchermo         paletteRossa
              paletteBlu          paletteU
              scalaColori         cancellaMenu
              strConv             drawCursor
              disegnaContorno     disegnaBaricentro
              disegnaDVU
              disegnaDensita      disegnaNodi
              disegnaElementi     disegnaVettori
              disegnaElemento
              lineaFlusso         disegnaLinee
              disegnaTutto        inputDisegno
              inser               inserI
              dati                dominio
              resetSim
              --->calcolaPotenziale   -->calcolaEulero
              output              demo
              ->fileProc          ->help
              menuPrincipale      checkMenu
              MAIN
}

{*********************************************************************}
Function t(R:real):integer;               { conversione real->integer }
begin
     t:=trunc(R);
end;


{*********************************************************************}
Procedure pausa;                     {attende la pressione di un tasto}

var key:char;
begin
     key:=readKey;
end;


{*********************************************************************}
Procedure apriSchermo;               { Apertura dello schermo grafico }

Var ErrorCode,GraphMode,GraphDriver :integer;

begin
     graphDriver:=Detect;
     {graphMode:=getMaxMode;}
     detectGraph(graphDriver,graphMode);
     initGraph(graphDriver,graphMode,'\TP\BGI');
     errorCode:=graphResult;
     if errorCode<>grOk then
        begin
             writeln('Errore grafico :',graphErrorMsg(errorCOde));
             halt;
        end;
     maxColors:=getMaxColor;
end;

{*********************************************************************}
procedure PaletteRossa;         { ridefinizione colori per la velocit…}

var  i ,r,g,b :integer;
     k,min :integer;

{ ERR: non ridefinisce i colori dall'8 al 15  e il 6 !!! }
begin
     setRgbPalette(0 ,0,0,0);
     min:=32;
     k:=(63-min) div 7;
     for i:=1 to 7 do begin
         r:=k*i+min;  g:=0;  b:=0;
         setRgbPalette(i ,r,g,b);
         end;
end;

{********************************}
procedure PaletteBlu;         { ridefinizione colori per la densit…}

var  i ,r,g,b :integer;
     k,min :integer;

{ ERR: non ridefinisce i colori dall'8 al 15  e il 6 !!! }
begin
     setRgbPalette(0 ,0,0,0);
     min:=32;
     k:=(63-min) div 7;
     for i:=1 to 7 do begin
         r:=0;  g:=0;  b:=k*i+min;
         setRgbPalette(i ,r,g,b);
         end;
end;

{********************************}
procedure PaletteU;          { ridefinizione colori per il potenziale}

var  i ,r,g,b :integer;
     k,min :integer;

{ ERR: non ridefinisce i colori dall'8 al 15  e il 6 !!! }
begin
     setRgbPalette(0 ,0,0,0);
     min:=32;
     k:=(63-min) div 7;
     for i:=1 to 7 do begin
         r:=k*i+min;  g:=0;  b:=k*i+min;
         setRgbPalette(i ,r,g,b);
         end;
end;

{********************************}
procedure scalaColori;      {visualizza la scala dei colori}

var i:integer;

begin
    { for i:=0 to 15 do begin
         str(i,s);
         setColor(i); outTextXY(100,10*i+100,s);
         end;}
     if not(gOpz4) and not(gOpz3) and not(gOpz7) then exit;
     setFillStyle(0,0); bar(0,70,20,140);
     setColor(10);
     if gOpz4 then begin outTextXY(0,50,'Velocit…');
                         outTextXY(0,60,'m/s'); end
     else if gOpz3 then begin outTextXY(0,50,'Densit…');
                              outTextXY(0,60,'Kg/m^3'); end
     else if gOpz7 then begin outTextXY(0,50,'Potenziale');
                              outTextXY(0,60,'J'); end;
     for i:=0 to 6 do begin
         if i<6 then setColor(i) else setColor(7);
         outTextXY(0,10*i+70,'ÜÜ'); {Ü=220}
         {}
         end;
end;


{*********************************************************************}
procedure cancellaMenu;         {cancella la barra del menu}

begin
     setFillStyle(0,0);
     bar(0,My-10,Mx,My);
     bar(0,0,Mx,20);
end;


{***********************************}
function strConv(V :real):string; { conversione di numeri reali in stringhe }

var  s :string;

begin
      str(V,s);
      strConv:=s;
end;


{*********************************}
function intStr(V :integer):string; { conversione di integer in stringhe }

var s :string;

begin
     str(V,s);
     intStr:=s;
end;


{*********************************}
procedure GetDVUmax;    {cerca i valori massimi e minimi delle variabili}

var i :integer;
    V :real;  { velocit… }

begin
     Dmax:=1e-10; Vmax:=1e-10; Umax:=1e-10;
     Dmin:=1e20; Vmin:=1e20; Umin:=1e20;
     for i:=1 to nDat do begin
         with Dat[i] do begin
              if d>(densIniz*10) then d:=densIniz*10; {}
              if d>Dmax then Dmax:=d;
              if d<Dmin then Dmin:=d;
              V:=sqrt(vx*vx+vy*vy);
              if V>Vmax then Vmax:=V;
              if V<Vmin then Vmin:=V;
              if U>Umax then Umax:=U;
              if U<Umin then Umin:=U;
              end;
         end;
end;

{*********************************}
procedure drawCursor(x,y,color :integer);  {disegna il cursore per l'inserimento del modello}

begin
     setColor(color);
     setWriteMode(XORput);
     line(0,y,Mx,y);
     line(x,15,x,My-15);
     setWriteMode(copyPut);
end;


{***********************************}
procedure disegnaContorno;                     { disegno del modello }

var  i :integer;
     polig :array [1..maxVert] of pointType;

begin
     setColor(15);
     putPixel(t(modello[1].x),t(modello[1].y),15);
     moveTo(t(modello[1].x),t(modello[1].y));
     for i:=2 to nVert do begin
         lineTo(t(modello[i].x),t(modello[i].y));
         end;
     for i:=1 to nVert do begin
         polig[i].x:=trunc(modello[i].x);
         polig[i].y:=trunc(modello[i].y);
         end;
     setFillStyle(1,8);
     fillPoly(nVert,polig);
end;


{************************************}
procedure disegnaBaric;                        { disegno del baricentro }

begin
     setColor(9);
     with centroMod do begin
          line(t(x-5),t(y),t(x+5),t(y));
          line(t(x),t(y-5),t(x),t(y+5));
     end;
end;


{************************************}
function elemento(x,y:integer):integer;  { ritorna l'elemento su cui si trova il punto (x,y) }
                                         { -1=fuori campo;  -2=sull'oggetto }
var N,minN :integer; {indici dell'elemento}
    dist,minDist :real; {distanza al quadrato}

begin
     minN:=-1;
     minDist:=100000;
     for N:=1 to nDat do begin
         dist:=sqr(x-Dat[N].cx)+sqr(y-Dat[N].cy);
         if dist<minDist then begin
                         minN:=N;
                         minDist:=dist;
                         end;
         end;
     if minN>(nDat-nPunti) then minN:=-1;
{     if minN<=(nPunti) then minN:=-2; {}
     elemento:=minN;
end;



{************************************}
procedure disegnaDVU(Flag:char);   { disegno della densit…,della velocit… e del potenziale}

var  i,colore :integer;
     Kd,Kv,kU :real;      { costanti per il colore }
     poly : array[0..4] of record
          x,y :integer;
          end;

begin
     GetDVUmax;
     if Flag='V' then paletteRossa else if Flag='D' then paletteBlu else paletteU;
     Kd:=7/Dmax;
     Kv:=7/Vmax;
     kU:=7/Umax;
     for i:=1 to nDat do begin
         with Dat[i] do begin
              if Flag='V' then colore:=trunc(sqrt(vx*vx+vy*vy)*Kv)
              else if Flag='D' then colore:=trunc(d*Kd)
                   else colore:=trunc(U*kU);
              if colore>5 then colore:=7       {}
              else if colore<0 then colore:=0;
              setColor(colore);
              setFillStyle(1,colore);
              poly[0].x:=t(nodo[p[1]].x); poly[0].y:=t(nodo[p[1]].y);
              poly[1].x:=t(nodo[p[2]].x); poly[1].y:=t(nodo[p[2]].y);
              poly[2].x:=t(nodo[p[3]].x); poly[2].y:=t(nodo[p[3]].y);
              poly[3].x:=t(nodo[p[4]].x); poly[3].y:=t(nodo[p[4]].y);
              poly[4].x:=poly[0].x;  poly[4].y:=poly[0].y;
              fillPoly(4,poly);
              end;
         end;
end;

{************************************}
procedure disegnaNodi;                         { disegno dei nodi }

var  i :integer;

begin
     for i:=1 to nNodi do begin
         putPixel(t(nodo[i].x),t(nodo[i].y),10);
         end;
end;


{************************************}
procedure disegnaElementi;                 { disegno degli elementi finiti }

var  i :integer;

begin
     setColor(9);
     for i:=1 to nDat do begin
         with Dat[i] do begin
              line(t(nodo[p[1]].x),t(nodo[p[1]].y),t(nodo[p[2]].x),t(nodo[p[2]].y));
              line(t(nodo[p[2]].x),t(nodo[p[2]].y),t(nodo[p[3]].x),t(nodo[p[3]].y));
              line(t(nodo[p[3]].x),t(nodo[p[3]].y),t(nodo[p[4]].x),t(nodo[p[4]].y));
              line(t(nodo[p[4]].x),t(nodo[p[4]].y),t(nodo[p[1]].x),t(nodo[p[1]].y));
              end;
         end;
end;


{************************************}
procedure disegnaVettori;    {disegno dei vettori velocit…}

var  i :integer;
     xc,yc,x,y :real;
     scala,V :real;

begin
     if (Vmax>noZ) then scala:=lungVettore/Vmax else scala:=0;
     for i:=1 to nDat do begin
         with Dat[i] do begin
              xc:=(nodo[p[1]].x+nodo[p[2]].x+nodo[p[3]].x+nodo[p[4]].x)/4; { centro dell'elemento }
              yc:=(nodo[p[1]].y+nodo[p[2]].y+nodo[p[3]].y+nodo[p[4]].y)/4;
              x:=xc+trunc(vx*scala); { punta del vettore }
              y:=yc+trunc(vy*scala);
              {V:=sqrt(sqr(vx)+sqr(vy))+noZ; {}
              {x:=trunc(20*vx/V+xc); {}
              {y:=trunc(20*vy/V+yc); {}
              setColor(14);  line(t(xc),t(yc),t(x),t(y));
              putPixel(t(xc),t(yc),15);
              end;
         end;
end;


{************************************}
procedure disegnaVettori2;             {disegno dei vettori velocit…}

var  cx,cy,x,y :integer;
     scala,V :real;
     i :integer;

begin
     if (Vmax>noZ) then scala:=lungVettore/Vmax else scala:=0;
     cx:=deltaS;
     repeat
           cy:=deltaS;
           repeat
                 i:=elemento(cx,cy);
                 if i=-1 then begin
                    x:=cx+trunc(xVel*scala);
                    y:=cy+trunc(yVel*scala);
                    end
                 else begin
                    x:=cx+trunc(Dat[i].vx*scala);
                    y:=cy+trunc(Dat[i].vy*scala);
                    end;
                 setColor(14);
                 line(cx,cy,x,y);
                 putPixel(cx,cy,15);
                 inc(cy,deltaS);
           until cy>My;
           inc(cx,deltaS);
     until cx>Mx;
end;


{************************************}
procedure disegnaElemento;  {}  {disegno di un singolo elemento}

var i :integer;

begin
     setColor(10);
     outTextXY(0,50,'i:'); gotoXY(1,1); readln(i);
     {if i<0 then exit;}
     with Dat[i] do begin
              line(t(nodo[p[1]].x),t(nodo[p[1]].y),t(nodo[p[2]].x),t(nodo[p[2]].y));
              line(t(nodo[p[2]].x),t(nodo[p[2]].y),t(nodo[p[3]].x),t(nodo[p[3]].y));
              line(t(nodo[p[3]].x),t(nodo[p[3]].y),t(nodo[p[4]].x),t(nodo[p[4]].y));
              line(t(nodo[p[4]].x),t(nodo[p[4]].y),t(nodo[p[1]].x),t(nodo[p[1]].y));
              outTextXY(0,100,'i  = '+strConv(i));
              outTextXY(0,110,'p1 = '+strConv(p[1]));
              outTextXY(0,120,'p2 = '+strConv(p[2]));
              outTextXY(0,130,'p3 = '+strConv(p[3]));
              outTextXY(0,140,'p4 = '+strConv(p[4]));
              outTextXY(0,160,'e1 = '+strConv(e[1]));
              outTextXY(0,170,'e2 = '+strConv(e[2]));
              outTextXY(0,180,'e3 = '+strConv(e[3]));
              outTextXY(0,190,'e4 = '+strConv(e[4]));
              setColor(14);
              if e[1]>=0 then line(t(cx),t(cy),t(Dat[e[1]].cx),t(Dat[e[1]].cy));
              if e[2]>=0 then line(t(cx),t(cy),t(Dat[e[2]].cx),t(Dat[e[2]].cy));
              if e[3]>=0 then line(t(cx),t(cy),t(Dat[e[3]].cx),t(Dat[e[3]].cy));
              if e[4]>=0 then line(t(cx),t(cy),t(Dat[e[4]].cx),t(Dat[e[4]].cy));
              end;
     readln;
end;



{************************************}
procedure lineaFlusso(x,y:integer); {disegna una linea di flusso dal punto x,y} {}

var  counter,i :integer;
     k :real;

begin
     putPixel(x,y,13); moveTo(x,y);
     k:=kLinee/Vel;
     counter:=0;
     repeat
           i:=elemento(x,y);
           if i=-1 then begin   {fuori campo}
                        x:=x+trunc(xVel*k);
                        y:=y+trunc(yVel*k);
                        end
           else if i=-2 then begin  {sul corpo}
                        counter:=1001;
                        end
                   else begin       {nel campo}
                        x:=x+trunc(Dat[i].vx*k);
                        y:=y+trunc(Dat[i].vy*k);
                        end;
           lineTo(x,y);
           inc(counter);
     until (x>Mx) or (x<0) or (y>My) or (y<0) or (counter>200) or keyPressed;
end;

{***********************}
procedure disegnaLinee;       { disegna le linee di flusso del fluido }

var  y :integer;

begin
     disegnaContorno;
     setColor(13);
     y:=20;
     repeat
           lineaFlusso(0,y);
           y:=y+passoLinee;
     until (y>=460) or keyPressed;
end;


{************************************}
procedure disegnaTutto;                            {genera l'output grafico}

begin
     clearViewPort;
     disegnaContorno;
     if noData then exit;
     if gOpz3 then disegnaDVU('D');
     if gOpz4 then disegnaDVU('V');
     if gOpz7 then disegnaDVU('U');
     if gOpz1 then disegnaElementi;
     if gOpz2 then disegnaNodi;
     if gOpz6 then disegnaLinee;
     if gOpz0 then disegnaElemento;
     if gOpz5 then disegnaVettori;
     if gOpz8 then disegnaVettori2;
     if gOpz3 or gOpz4 or gOpz7 then scalaColori;
     disegnaContorno;
     disegnaBaric;
end;


{*********************************************************************}
procedure printCoord(x,y,cursX0,cursY0 :integer);  {scrive le coordinate del cursore}
     begin
     setFillStyle(0,0);
     bar(0,My-30,100,My-40);
     setColor(11);
     outTextXY(0,My-40,intStr(x-cursX0)+' ; '+intStr(cursY0-y));
     end;



{*********************************************************************}
procedure inputDisegno;                           { input del modello }

var  x,y :integer;   { posizione cursore }
     cursX0,cursY0 :integer;  { origine per il cursore }
     dl :integer;    { spostamento cursore }
     key :char;

begin
     clearViewPort;
     setColor(15);
     outTextXY(0,0,'Disegno del modello.');
     outTextXY(0,My-10,'ZXMK.spostamento  [spazio].conferma  [backSpace].cancella  [return].menu  +-');
     x:=Mx div 2;  y:=My div 2;  dl:=4;
     cursX0:=x; cursY0:=y;
     drawCursor(x,y,10);
     nVert:=0;

     repeat
           key:=readKey;
           drawCursor(x,y,10);
           if (key='z') and (x>0) then dec(x,dl);         { spost. cursore }
           if (key='x') and (x<Mx) then inc(x,dl);
           if (key='k') and (y>25) then dec(y,dl);
           if (key='m') and (y<My-15) then inc(y,dl);
           drawCursor(x,y,10);
           printCoord(x,y,cursX0,cursY0);
           if (key='+') then dl:=2*dl;                    { cambio spost. }
           if (key='-') and (dl>1) then dl:=dl div 2;
           if (key=' ') and (nVert<maxVert) then begin     { disegna linea }
                                            inc(nVert);
                                            modello[nVert].x:=x;
                                            modello[nVert].y:=y;
                                            disegnaContorno;
                                            end;
           if (key=chr(8)) and (nVert>0) then begin       { cancella linea }
                                         dec(nVert);
                                         setFillStyle(0,0); bar(0,15,Mx,My-15);
                                         disegnaContorno;
                                         drawCursor(x,y,10);
                                         end;
     until (key=chr(13)) or (nVert>=maxVert-2);

     if (modello[nVert].x<>modello[1].x)or(modello[nVert].y<>modello[1].y) then begin   {chiude il profilo}
                                   inc(nVert); modello[nVert]:=modello[1];
                                   end;
     newFile:=true;
     clearViewPort;
     centroMod.x:=0; centroMod.y:=0;    { calcolo del centro del modello }
     for i:=1 to (nVert-1) do begin
         centroMod.x:=centroMod.x+modello[i].x;
         centroMod.y:=centroMod.y+modello[i].y;
         end;
     centroMod.x:=centroMod.x/(nVert-1);
     centroMod.y:=centroMod.y/(nVert-1);

end;


{***********************************************************************}
procedure  inser(msg :string; Var valore :real);   { input di dati real }

var  temp :string;
     err :integer;

begin
     setColor(0); bar(0,350,300,385);
     setColor(15); outTextXY(0,355,msg);
     outTextXY(0,370,' [ '+strConv(valore)+' ] ');
     textColor(15); gotoXY(21,23); readln(temp);
     if temp<>'' then val(temp,valore,err);
end;


{*********************************}
procedure inserI(msg :string; Var valore :integer);   { input di dati integer }

var  temp :string;
     err :integer;

begin
     setColor(0); bar(0,350,300,385);
     setColor(15); outTextXY(0,355,msg);
     outTextXY(0,370,' [ '+strConv(valore)+' ] ');
     textColor(15); gotoXY(21,23); readln(temp);
     if temp<>'' then val(temp,valore,err);
end;


{*********************************}
procedure dati;                             { immissione dati }

var  k :char;
     Pmax :real;

begin
     repeat
           clearViewPort;
           setColor(15);
           outTextXY(0,0,'DATI SIMULAZIONE (sistema MKS):');
           setColor(10);
           outTextXY(0,30,'Velocit… massima (m/s)    = '+strConv(Vmax));
           outTextXY(0,45,'         minima           = '+strConv(Vmin));
           outTextXY(0,70,'Densit… massima (Kg/m^3)  = '+strConv(Dmax));
           outTextXY(0,85,'        minima            = '+strConv(Dmin));
           {Pmax:=k1P*Dmax^k2P; {}
           outTextXY(0,110,'Pressione massima (N/m^2) = '+strConv(Pmax));
           outTextXY(0,125,'          minima          = '); {}
           setColor(15);
           outTextXY(0,170,'DATI INIZIALI (sistema MKS):');
           setColor(10);
           outTextXY(0,190,'1. Quanto di tempo (s)        dT = '+strConv(dT));
           outTextXY(0,205,'2. Velocit… (m/s)              V = '+strConv(vel));
           outTextXY(0,220,'3. Angolo di attacco (deg)   AoA = '+strConv(angAtt));
           outTextXY(0,235,'4. Densit… aria (Kg/m^3)       d = '+strConv(densIniz));
           outTextXY(0,290,'Scegli un parametro da modificare (ENTER=esci)...');
           k:=readKey;
           if k='1' then inser('dT = ',dT);
           if k='2' then inser('V = ',vel);
           if k='3' then inser('AoA = ',angAtt);
           if k='4' then inser('d = ',densIniz);
     until (k='0') or (k=chr(13));
     clearViewPort;
end;


{*********************************************************************}
procedure  simulazione;             { impostazione dominio di calcolo }

var  k :char;
     maxLiv :integer;

begin
     repeat
           clearViewPort;
           setColor(15);
           outTextXY(0,0,'MODO SIMULAZIONE :');
           setColor(10);
           outTextXY(0,30,'   a. Metodo del potenziale.');
           outTextXY(0,50,'   b. Equazioni di Eulero.');
           if simMode=0 then outTextXY(0,30,'->') else outTextXY(0,50,'->');
           setColor(15);
           outTextXY(0,100,'PARAMETRI INIZIALI DI CALCOLO :');
           setColor(10);
           outTextXY(0,130,'1. Numero  di livelli = '+strConv(nLivelli));
           outTextXY(0,150,'2. Numero  di punti su un livello = '+strConv(nPunti));
           outTextXY(0,170,'3. Incremento del numero di punti = '+incrPunti);
           outTextXY(0,190,'4. Scala livelli = '+strConv(scala));
           k:=readKey;
           if k='a' then simMode:=0;
           if k='b' then simMode:=1;
           if k='1' then inserI('n = ',nLivelli);
           if k='2' then inserI('N = ',nPunti);
           if k='3' then begin
                  {  if incrPunti='n' then incrPunti:='s' else incrPunti:='n'; }
                    end;
           if k='4' then inser('Scala = ',scala);
           maxLiv:=maxElem div nPunti;
           if (nLivelli<0) or (nLivelli>maxLiv) then nLivelli:=maxLiv;
     until  (k='0') or (k=chr(13));
     clearViewPort;
end;

{*****************************}
procedure stampaDati;         {stampa dati ad ogni ciclo di calcolo}

begin
     setColor(10);
     outTextXY(0,30,'Tempo='+strConv(tempo)+' s. ');
end;


{**********************************************************************}
procedure resetSim;                          { definizione del sistema }

var  N :integer;    { indice di  nodo[]  }
     i,j,max,liv,p :integer;
     perimetro,lato,dist :real;
     nodiLato :integer; {numero di nodi su ogni lato}
     x0,y0 :real;  {coordinate del primo nodo di un lato}
     dx,dy :real;  {differenza di coordinate tra due nodi sullo stesso lato}
     maxX,minX :real;  {ascisse massime e minime dei centri degli elementi}
     deltaX :real;     { =maxX-minX }

begin
     if (nPunti<=0) or (nVert<=1) then exit;
     perimetro:=0;               { calcolo del perimetro del modello }
     for i:=1 to (nVert-1) do begin
         lato:=sqrt(sqr(modello[i].x-modello[i+1].x)+sqr(modello[i].y-modello[i+1].y));   { lunghezza del lato }
         perimetro:=perimetro+lato;
         end;
     dist:=perimetro/nPunti;


     for i:=0 to maxNodi do begin
         nodo[i].x:=0; nodo[i].y:=0; nodo[i].c:=0;
         end;

     { ---- nodi sul primo livello (strato limite) ---- }
     nodiLato:=nPunti div (nVert-1);   { nodi per ciascun lato }
     if nodiLato=0 then nodiLato:=1;
     nPunti:=nodiLato*(nVert-1);       { numero di punti effettivamente presenti per ogni livello }
     N:=0;   { indice di nodo[] }
     for i:=1 to (nVert-1) do begin
         dx:=(modello[i+1].x-modello[i].x)/nodiLato;
         dy:=(modello[i+1].y-modello[i].y)/nodiLato;
         x0:=modello[i].x;  y0:=modello[i].y;
         for j:=0 to (nodiLato-1) do begin
             inc(N);
             nodo[N].x:=x0+j*dx;
             nodo[N].y:=y0+j*dy;
             nodo[N].c:=1;
             end;
         end;

     { ---- nodi sul dominio di calcolo ---- }
     for i:=2 to nLivelli do begin
         for j:=1 to nPunti do begin
             inc(N);
             nodo[N].x:=(nodo[N-nPunti].x-centroMod.x)*scala+centroMod.x;
             nodo[N].y:=(nodo[N-nPunti].y-centroMod.y)*scala+centroMod.y;
             nodo[N].c:=0;
             end;
         end;

     newFile:=false;
     nNodi:=N;
     disegnaNodi;

     { ---- definizione degli elementi finiti ---- }
     Dmax:=densIniz;
     Vmax:=vel;
     xVel:=vel*cos(angAtt);
     yVel:=vel*sin(angAtt);

     i:=1;
     for liv:=1 to nLivelli-1 do begin
         for p:=1 to nPunti-1 do
             with Dat[i] do begin
                  d:=densIniz;  vx:=xVel;  vy:=yVel;  { dati fisici dell'elemento }
                  p[1]:=i;  { p1..p4 :indirizzi dei vertici dell'elemento }
                  p[2]:=p[1]+1;
                  p[4]:=p[1]+nPunti;
                  p[3]:=p[4]+1;
                  inc(i);
                  end;
         with Dat[i] do begin    { ultimo elemento del livello }
              d:=densIniz;  vx:=xVel;  vy:=yVel;
              p[1]:=i;
              p[2]:=p[1]+1-nPunti;
              p[4]:=p[1]+nPunti;
              p[3]:=p[4]+1-nPunti;
              inc(i);
              end;
         end;
     nDat:=i-1;

     { ---connessione degli elementi con i vicini--- }
     for liv:=2 to nLivelli-2 do begin  { elementi interni }
         for p:=2 to nPunti-1 do begin
             i:=p+nPunti*(liv-1);
             with Dat[i] do begin
                  e[1]:=i-1;        e[2]:=i+1;
                  e[3]:=i-nPunti;   e[4]:=i+nPunti;
                  end;
             end;
         end;

     liv:=1;                            { strato limite }
     for p:=2 to nPunti-1 do begin
         i:=p;
         with Dat[i] do begin
              e[1]:=i-1;    e[2]:=i+1;
              e[3]:=-1;     e[4]:=i+nPunti;
              end;
         end;

     liv:=nLivelli-1;                 { strato pi— esterno }
     for p:=2 to nPunti-1 do begin
         i:=p+nPunti*(liv-1);
         with Dat[i] do begin
              e[1]:=i-1;       e[2]:=i+1;
              e[3]:=i-nPunti;  e[4]:=-2;
              end;
         end;

     { connessione tra il primo e l'ultimo elem. di ogni livello }
     for liv:=2 to nLivelli-2 do begin
         i:=1+nPunti*(liv-1);
         with Dat[i] do begin
              e[1]:=i-1+nPunti;   e[2]:=i+1;
              e[3]:=i-nPunti;     e[4]:=i+nPunti;
              end;
         i:=nPunti*liv;
         with Dat[i] do begin
              e[1]:=i-1;        e[2]:=i+1-nPunti;
              e[3]:=i-nPunti;   e[4]:=i+nPunti;
              end;
         end;

     with Dat[1] do begin
          e[1]:=nPunti;   e[2]:=2;
          e[3]:=-1;       e[4]:=1+nPunti;
          end;

     with Dat[nPunti] do begin
          e[1]:=nPunti-1;   e[2]:=1;
          e[3]:=-1;         e[4]:=nPunti+nPunti;
          end;

     i:=nPunti*(nLivelli-1);
     with Dat[i] do begin
          e[1]:=i-1;        e[2]:=i+1-nPunti;
          e[3]:=i-nPunti;   e[4]:=-2;
          end;

     i:=1+nPunti*(nLivelli-2);
     with Dat[i] do begin
          e[1]:=i-1+nPunti;   e[2]:=i+1;
          e[3]:=i-nPunti;     e[4]:=-2;
          end;

     { calcolo dei centri degli elementi }
     i:=1;
     for liv:=1 to nLivelli do begin
         for p:=1 to nPunti-1 do begin
             with Dat[i] do begin
                  cx:=(nodo[p[1]].x+nodo[p[2]].x+nodo[p[3]].x+nodo[p[4]].x)/4; {centro dell'elemento}
                  cy:=(nodo[p[1]].y+nodo[p[2]].y+nodo[p[3]].y+nodo[p[4]].y)/4;
                  inc(i);
                  end;
             end;
         end;


     { assegnamento del potenziale iniziale }
     maxX:=-1000; minX:=1000;
     liv:=nLivelli-1; {seleziona l'ultimo livello}
     for p:=1 to nPunti-1 do begin  {trova i valori max. e min. delle ascisse dei centri degli elementi}
         i:=p+nPunti*(liv-1);
         if Dat[i].cx>maxX then maxX:=Dat[i].cx;
         if Dat[i].cx<minX then minX:=Dat[i].cx;
         end;
     deltaX:=maxX-minX;
     Uiniz:=xVel*deltaX; { valore del potenziale ad un'estremo del campo... }
                         { ...(all'estremo opposto U=0).  }
     i:=1;
     for liv:=1 to nLivelli do begin {calcolo del potenziale iniziale in ogni punto del campo}
         for p:=1 to nPunti-1 do begin
             Dat[i].U:=Uiniz*(deltaX-Dat[i].cx+minX)/deltaX;
             inc(i);
             end;
         end;


     disegnaElementi;
     disegnaNodi;
     tempo:=0;
     noData:=false;
     disegnaTutto;
end;


{**********************************************}
procedure askReset;                             { chiede se fare reset }

var  new,k :char;

begin
     cancellaMenu;
     if not(newFile) then begin
                     setColor(15);
                     outTextXY(0,0,'Devo ricominciare il calcolo (s/n) ?');
                     new:=readKey;
                     cancellaMenu;
                     end;
     if (newFile) or (new='s') then resetSim;
end;


{***********************************************************************}
procedure calcolaPotenziale;  {}                  { metodo del potenziale }

var  i :integer; {indice dell'elemento corrente}
     j :integer; {indice degli elementi confinanti con quello corrente}
     n :integer; {numero di elementi confinanti effettivamente presenti}
{     ds :array[1..4] of real; {distanze tra il centro dell'el. corrente e i centri degli el. confinanti}
{     dMedia :real;
{     U01,U02 :real;}
     cA,cB,cC,cD,cE,cF,cG,cH :real; {coefficienti} {}
     detM,detM1,detM2,detM3 :real; {determinanti} {}
     U1,U2,U3,U4 :real;
     V :real;    {modulo velocit…}
     vxj,vyj :real;  {componenti di V relative al j-esimo elemento}
     dx,dy :real;  {componenti della distanza tra i centri di due elementi confinanti}
     dldl :real;   {distanza al quadrato tra i centri di due elementi confinanti}
     dU :real;     {variazione del potenziale fra due elementi}
     temp :real;   {variabile per valori temporanei}

begin
     askReset;
     tempo:=0;

     repeat
           disegnaTutto;
           {stampaDati;}
           Vmax:=0.001;  Umax:=0.001;
                                             {loop principale}
           for i:=1 to (nDat-nPunti) do begin
               with Dat[i] do begin
                    {elementi al limite del dominio di calcolo}
                    if (e[1]<0) or (e[2]<0) or (e[3]<0) or (e[4]<0) then begin
                       n:=0;  U:=0;
                       if e[1]>=0 then begin
                                  U:=U+Dat[e[1]].U;
                                  inc(n);
                                  end;
                       if e[2]>=0 then begin
                                  U:=U+Dat[e[2]].U;
                                  inc(n);
                                  end;
                       if e[3]>=0 then begin
                                  U:=U+Dat[e[3]].U;
                                  inc(n);
                                  end;
                       if e[4]>=0 then begin
                                  U:=U+Dat[e[4]].U;
                                  inc(n);
                                  end;
                       U:=U/n;
                       end
                    {elementi interni al dominio di calcolo} {}
                    else begin
(*                         for j:=1 to 4 do    {calcolo delle distanze tra l'elemento ed i vicini}
                             ds[j]:=sqrt(sqr(cx-Dat[e[j]].cx)+sqr(cy-Dat[e[j]].cy));

                         {metodo della media}
                         U1:=Dat[e[1]].U;  U2:=Dat[e[2]].U;
                         U3:=Dat[e[3]].U;  U4:=Dat[e[4]].U;

                         U:=(U1+U2+U3+U4)*0.25;
*)

{}
                         { calcolo del potenziale della velocit… dall'equazione di Laplace: }
                         {    div grad U = Uxx + Uyy = 0 .                                  }
                         { Metodo della regressione lineare multipla:                       }
                         cA:=0; cB:=0; cC:=0; cD:=0; cE:=0; cF:=0; cG:=0; cH:=0; {azzero i coefficienti}
                         for j:=1 to 4 do begin
                             cA:=cA+Dat[e[j]].cx;
                             cB:=cB+Dat[e[j]].cy;
                             cC:=cC+Dat[e[j]].U;
                             cD:=cD+Dat[e[j]].cx*Dat[e[j]].cx;
                             cE:=cE+Dat[e[j]].cx*Dat[e[j]].cy;
                             cF:=cF+Dat[e[j]].cx*Dat[e[j]].U;
                             cG:=cG+Dat[e[j]].cy*Dat[e[j]].cy;
                             cH:=cH+Dat[e[j]].cy*Dat[e[j]].U;
                             end;
                         {calcolo dei determinanti}
                         detM :=4*(cD*cG-cE*cE)-cA*(cA*cG-cB*cE)+cB*(cA*cE-cB*cD);
                         detM1:=cC*(cD*cG-cE*cE)-cF*(cA*cG-cB*cE)+cH*(cA*cE-cB*cD);
                         detM2:=4*(cF*cG-cE*cH)-cA*(cC*cG-cB*cH)+cB*(cC*cE-cB*cF);
                         detM3:=4*(cD*cH-cE*cF)-cA*(cA*cH-cE*cC)+cB*(cA*cF-cD*cC);

                         U:=(detM1+detM2*cx+detM3*cy)/detM;
                         end;

                    if U>Umax then Umax:=U;
                    end; {with}
               end; {for}

           {calcolo velocit…:    V = -grad U  }
           if gOpz4 or gOpz5 or (random(20)=1) then begin
           for i:=1 to nDat do begin  {scandisce gli elementi di cui il campo Š costituito}
               with Dat[i] do begin
                    vx:=0;  vy:=0;
                    for j:=1 to 4 do begin  {scandisce gli elementi confinanti con l'elemento i-esimo}
                        if e[j]>=0 then begin
                           dx:=Dat[e[j]].cx-cx;  dy:=Dat[e[j]].cy-cy;
                           dldl:=dx*dx+dy*dy;  {distanza al quadrato tra i centri di due elementi adiacenti}
                           dU:=Dat[e[j]].U-U;  {differenza di potenziale}
                           temp:=-dU/dldl;
                           vxj:=temp*dx;  vyj:=temp*dy;  {velocit… relative al j-esimo elemento}
                           vx:=vx+vxj;  vy:=vy+vyj;
                           end;
                        end;
                    V:=sqrt(vx*vx+vy*vy);      {modulo del vettore velocit…}
                    if V>Vmax then Vmax:=V else if V<Vmin then Vmin:=V;
                    end; {with}
               end; {for}
               end; {if}

     until keyPressed;
end;


{***********************************************************************}
procedure calcolaEulero;                             { metodo di Eulero }

var  i :integer;   { indice dell'elemento corrente }
     V :real;      { modulo velocit… }
     P :real;      { pressione }

     elVicino :integer; { indirizzo dell'el. vicino }
     dens :real;        { densit… nell'el. vicino }
     velX,velY :real;   { velocit… dell'el. vicino }

     dDens :real;  { variazione di densit… in un elemento rispetto al tempo }
     lung :real;   { lunghezza del lato dell'elemento }
     Ax,Ay,Bx,By :real; { estremi del lato }
     m1,m2 :real;  { coefficienti angolari del vettore velocit… e del lato }
     fi :real;     { angolo tra il vettore velocit… e il lato }
     VelOrt :real; { componente ortogonale di V al lato }
     verso :integer; { +-1  verso di VelOrt }
     lato :integer; { indice del lato }

begin
     askReset;

     repeat               { loop principale }
           disegnaTutto;
           stampaDati;
           Vmax:=0.0;  Dmax:=0.0;
           tempo:=tempo+dT;

           for i:=1 to nDat do begin  {** calcolo variazione velocit… **}
               with Dat[i] do begin


                    V:=sqrt(vx*vx+vy*vy);
                    if V>Vmax then Vmax:=V;
                    end; {with}
               end; {for}

           for i:=1 to nDat do begin  {** calcolo variazione densit… **} {}
               with Dat[i] do begin
                    dDens:=0;
                    for lato:=1 to 4 do begin
                        Ax:=nodo[p[lato]].x;        { estremi del lato }
                        Ay:=nodo[p[lato]].y;
                        if lato=4 then begin
                                       Bx:=nodo[p[1]].x;
                                       By:=nodo[p[1]].y;
                                       end
                                  else begin
                                       Bx:=nodo[p[lato+1]].x;
                                       By:=nodo[p[lato+1]].y;
                                       end;
                        elVicino:=e[lato];  { indirizzo dell'el. vicino }
                        if elVicino>0 then begin
                                           dens:=Dat[elVicino].d;   { dati dell'el. vicino }
                                           velX:=Dat[elVicino].vx;
                                           velY:=Dat[elVicino].vy;
                                           end
                           else if elVicino=-2 then begin    { el. pi— esterno }
                                                    dens:=densIniz;
                                                    velX:=xVel; velY:=yVel;
                                                    end
                           else if elVicino=-1 then begin
                                                    dens:=0; { el. a contatto col corpo }
                                                    velX:=0; velY:=0;
                                                    end;
                        lung:=sqrt(sqr(Bx-Ax)+sqr(By-Ay))*scalaDis;  { lunghezza del lato in metri }
                      (*  m1:=velY/(velX+noZ); { coefficiente angolare del vettore velocit… }
                        m2:=(By-Ay)/(Bx-Ax+noZ); { coefficiente angolare del lato dell'elemento }
                        fi:=arcTan((m2-m1)/(1+m1*m2)); { angolo tra i vettori velocit… e lato }
                        verso:=1; {}
                        VelOrt:=sqrt(sqr(velX)+sqr(velY))*abs(sin(abs(fi)))*verso; { componente di V ortogonale al lato }
                        dDens:=dDens+VelOrt*dens*lung; { eq. di continuit… } *)
                        fi:=arcTan((By-Ay)/(Bx-Ax+noZ)); {}
                        dDens:=dDens+(velX*sin(fi)+velY*cos(fi))*lung*dens;
                        end;
                    d:=d+dDens*dT;   { variazione densit… }
                    if d<0 then d:=0;
                    if d>Dmax then Dmax:=d;
                    end; {with}
               end; {for}

     until keyPressed;
end;


{*********************************************************************}

{*********************************************************************}
procedure output;                        { scelta dell'output grafico }

var  key :char;

begin
     repeat
           clearViewPort;
           setColor(15);
           outTextXY(0,0,'OUTPUT GRAFICO :');
           setColor(10);
           outTextXY(0,40,'   1. Elementi finiti.');
           outTextXY(0,60,'   2. Nodi.');
           outTextXY(0,80,'   3. Densit… del fluido.');
           outTextXY(0,100,'   4. Modulo velocit….');
           outTextXY(0,120,'   5. Vettori velocit….');
           outTextXY(0,140,'   6. Linee di flusso.');
           outTextXY(0,160,'   7. Potenziale.');
           outTextXY(0,180,'   8. Vettori velocit… (b).');
           outTextXY(0,220,'[enter] - esci.');
           setColor(15);
           if gOpz0 then outTextXY(0,300,'*');
           if gOpz1 then outTextXY(0,40,'>');
           if gOpz2 then outTextXY(0,60,'>');
           if gOpz3 then outTextXY(0,80,'>');
           if gOpz4 then outTextXY(0,100,'>');
           if gOpz5 then outTextXY(0,120,'>');
           if gOpz6 then outTextXY(0,140,'>');
           if gOpz7 then outTextXY(0,160,'>');
           if gOpz8 then outTextXY(0,180,'>');
           key:=readKey;
           if key='0' then gOpz0:=not(gOpz0);
           if key='1' then gOpz1:=not(gOpz1);
           if key='2' then gOpz2:=not(gOpz2);
           if key='3' then gOpz3:=not(gOpz3);
           if key='4' then gOpz4:=not(gOpz4);
           if key='5' then gOpz5:=not(gOpz5);
           if key='6' then gOpz6:=not(gOpz6);
           if key='7' then gOpz7:=not(gOpz7);
           if key='8' then gOpz8:=not(gOpz8);
     until key=chr(13);
     disegnaTutto;
end;



{*********************************************************************}
procedure inputDati;                              { input da tastiera }

var  i :integer;

begin
     clearViewPort;
     setColor(15);
     outTextXY(0,0,'INSERIMENTO DATI:');
     inserI('Elemento n.:',i);
     if i>maxElem then i:=maxElem;
     with Dat[i] do begin
          inser('Densit… (Kg/m^3) = ',densIniz);
          inser('Vx      (m/s)    = ',vx);
          inser('Vy      (m/s)    = ',vy);
          inser('U       (J)      = ',U);
          end;
     disegnaTutto;
end;

{*********************************************}
procedure inputBaric;

var  key: char;
     dl: integer;
     cursX0,cursY0 :integer;

begin
     dl:=4;
     cursX0:=Mx div 2;  cursY0:=My div 2;
     with centroMod do begin
          drawCursor(t(x),t(y),13);
          repeat
           key:=readKey;
           drawCursor(t(x),t(y),13);
           if (key='z') and (x>0) then x:=x-dl;         { spost. cursore }
           if (key='x') and (x<Mx) then x:=x+dl;
           if (key='k') and (y>25) then y:=y-dl;
           if (key='m') and (y<My-15) then y:=y+dl;
           drawCursor(t(x),t(y),13);
           printCoord(t(x),t(y),cursX0,cursY0);
           if (key='+') then dl:=2*dl;                    { cambio spost. }
           if (key='-') and (dl>1) then dl:=dl div 2;
           until (key=chr(13));
          end; {with}
end;

{*********************************************}
procedure leggiDati;          {stampa i dati relativi all'elemento indicato}

var  key :char;
     x,y,dl :integer;
     elem :integer;
     V :real;

begin
     setColor(0); bar(0,My,Mx,My-10);
     dl:=4;
     x:=Mx div 2;  y:=My div 2;
     drawCursor(x,y,13);
     repeat
           key:=readKey;
           drawCursor(x,y,13);
           if (key='z') and (x>0) then x:=x-dl;         { spost. cursore }
           if (key='x') and (x<Mx) then x:=x+dl;
           if (key='k') and (y>25) then y:=y-dl;
           if (key='m') and (y<My-15) then y:=y+dl;
           drawCursor(x,y,13);
           if (key='+') then dl:=2*dl;                    { cambio spost. }
           if (key='-') and (dl>1) then dl:=dl div 2;
           if (key=' ') then begin
                        elem:=elemento(x,y);
                        setColor(0); bar(0,380,220,My);
                        setColor(11);
                        if elem>=0 then begin
                                   with Dat[elem] do begin
                                   outTextXY(0,380,'N ='+strConv(elem));
                                   outTextXY(0,400,'d ='+strConv(d));
                                   outTextXY(0,415,'U ='+strConv(U));
                                   outTextXY(0,430,'Vx='+strConv(vx));
                                   outTextXY(0,445,'Vy='+strConv(vy));
                                   V:=sqrt(sqr(vx)+sqr(vy));
                                   outTextXY(0,460,'V ='+strConv(V));
                                   end; end
                        else begin
                             outTextXY(0,400,'Fuori campo.');
                             end;
                        end;
     until (key=chr(13));
     disegnaTutto;
end;


{*********************************************}
procedure changeZoom;             {cambia la scala del disegno}
begin
     clearViewPort;
     setColor(15);
     outTextXY(0,0,'Zoom attuale: '+strConv(zoom));
     inser('Zoom = ',zoom);
     disegnaTutto;
end;


{*********************************************************************}
procedure fileProc;           {si occupa della gestione dei files}

var opz :char;
    y :integer;

begin
     cancellaMenu;
     setColor(15);
     y:=getMaxY-10;
     outTextXY(0,y,'1.Load    2.Save    3.Test    0.Menu principale');
     repeat
           opz:=readKey;
           case opz of
           '1': ;
           '2': ;
           '3': begin                   { test programma }
                     vel:=100;  angAtt:=0;
                     densIniz:=1.300010;

                end;
           end;
     until opz='0';
end;



{*********************************************************************}
procedure demo;                                  {dimostrazione}

var x0,y0 :integer;   {centro dello schermo}

begin
     vel:=100;  angAtt:=0;
     densIniz:=1.300010;
     x0:=Mx div 2;  y0:=My div 2;  {centro schermo}
     modello[1].x:=x0-40;   modello[1].y:=y0;  {vertici del profilo}
     modello[2].x:=x0;   modello[2].y:=y0+40;
     modello[3].x:=x0+12;   modello[3].y:=y0;
     modello[4].x:=x0;   modello[4].y:=y0-40;
     modello[5].x:=modello[1].x;   modello[5].y:=modello[1].y;
     nVert:=5; {numero di vertici}

     centroMod.x:=0; centroMod.y:=0;    { calcolo del centro del modello }
     for i:=1 to (nVert-1) do begin
         centroMod.x:=centroMod.x+modello[i].x;
         centroMod.y:=centroMod.y+modello[i].y;
         end;
     centroMod.x:=centroMod.x/(nVert-1);
     centroMod.y:=centroMod.y/(nVert-1);

     gOpz2:=false; gOpz4:=false; gOpz5:=false; {opzioni per l'output}
     gOpz2:=true; resetSim; pausa;
     gOpz1:=true; disegnaTutto; pausa;
     gOpz1:=false; gOpz2:=false;
     gOpz4:=true; gOpz5:=true;
     newFile:=true;
     calcolaPotenziale;
end;


{*********************************************************************}
procedure help;                                  {istruzioni per l'uso}

begin
     clearViewPort;
     setColor(15);  outTextXY(0,300,'ALTRI TASTI UTILIZZABILI :');
     setColor(10);
     outTextXY(0,350,'r : ridisegna lo schermo.');
     outTextXY(0,365,'s : visualizza la scala dei colori.');
     outTextXY(0,380,'z : zoom: cambia le dimensioni del disegno.');
     outTextXY(0,395,'i : ');
     outTextXY(0,410,'b : posizionamento manuale del baricentro.');
     outTextXY(0,425,'p : restituisce il valore delle variabili nel punto indicato.');
     repeat until keyPressed;
     disegnaTutto;
end;


{*********************************************************************}
procedure menuPrincipale;                           { menu principale }

var  x,y :integer;

begin
     cancellaMenu;
     setColor(13);
     outTextXY(1,1,'C.F.D.');
     setColor(15);
     outTextXY(1,10,'Vers. 1   Pietro Mele,  6/1994.');
     Mx:=getMaxX;  My:=getMaxY;
     x:=0; y:=My-10;
     outTextXY(x,y-15,'d.Demo');
     outTextXY(x,y,'1.Disegna   2.Dati   3.Simulazione   4.Calcola   5.Output   6.File   E.Esci  h=?');
end;


{********************************************************************}
procedure checkMenu;                                { controllo menu }

var  opz :char;

begin
     repeat
           disegnaContorno;
           disegnaBaric;
           menuPrincipale;
           opz:=readKey;
           case opz of
           '1': inputDisegno;
           '2': dati;
           '3': simulazione;
           '4': if simMode=0 then calcolaPotenziale else calcolaEulero;
           '5': output;
           '6': fileProc;
           'r': disegnaTutto;
           'i': inputDati;
           's': scalaColori;
           'z': changeZoom;
           'h': help;
           'b': inputBaric;
           'p': leggiDati;
           'd': demo;
           'D': demo;
           end;
     until opz='E';
end;


{*********************************************************************}
procedure presentazione;

var i,j:integer;
    k:real;

begin
     for i:=1 to 30 do writeln('');
     textColor(12);
     writeln('C.F.D. 1992-94');
     writeln('----------------------------------');
     textColor(7);
     writeln;
     writeln('   Programma per la simulazione del moto di un fluido attorno ad un');
     writeln('oggetto il cui profilo viene disegnato dalla tastiera.');
     writeln('   Ho scritto il programma in Pascal e ho fatto uso dell"equazione del');
     writeln('potenziale, dal quale si ricava la velocit… derivando. Il fluido');
     writeln('proviene da sinistra.');
     writeln('   Per una dimostrazione sul funzionamento del programma scegliete');
     writeln('l"opzione d (demo), che utilizza un profilo predefinito. Attendere');
     writeln('poi che il programma esegua un numero sufficiente di iterazioni.');
     writeln; writeln; writeln;
     writeln('                                          Pietro Mele');
     writeln('                                          via Giardino 6');
     writeln('                                          37126, Verona');
     writeln('                                          tel. 045/91.68.35');
     readkey;
     for i:=1 to 30 do begin
         writeln('');
         for j:=1 to 2000 do begin k:=sqrt(j); end; {questo serve solo per rallentare il ciclo}
         end;
end;


{=========================================== MAIN ====================}

begin
     nomeModello:='TEST.MOD';     { var. file }
     nomeSimulaz:='TEST.SIM';
     newFile:=true;
     nPunti:=40;  nLivelli:=10;
     scala:=1.30;
     incrPunti:='n';

     simMode:=0;
     dT := 0.01;   tempo := 0;   { var. simulazione }
     scalaDis := 10/640; { metri/pixels }
     vel := 0;  angAtt := 0;
     densIniz:= 1.300010;
     k1P := 1;     { ? costanti per l'eq. di stato }
     k2P := 1.3;   { Cp/Cv ? }

     zoom:=1;                    { var. grafica }
     gOpz0:=false;
     gOpz1:=false;  gOpz2:=true;  gOpz3:=false;  gOpz4:=false;
     gOpz5:=false;  gOpz6:=false; gOpz7:=false;  gOpz8:=false;
     lungVettore:=10;  deltaS:=lungVettore*2;  {}
     passoLinee:=20;  kLinee:=5;
     noData:=true;

     presentazione;
     apriSchermo;
     PaletteRossa;
     scalaColori;

     checkMenu;

     closeGraph;
end.