Dynamique des Fluides, Simulation

Programmation d'applications complexes
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Dynamique des Fluides, Simulation

Message par graph100 »

Suite au poste de Huitbit, je me suis tortillé les neurones et j'ai porté le travail présenté dans le document suivant sur PB :
http://www.intpowertechcorp.com/GDC03.pdf

C'est bien rigolo, mais pour le moment ce n'est qu'un code qui refait absolument la même chose,
j'espère pouvoir vous faire une petite personnalisation plus tard :D

Le code de mise en œuvre est assez sale, mais la partie de simulation est super propre 8)

[EDIT] Version 2, mise à jour

Code : Tout sélectionner

;{######################################
; Programme : 		Dynamique des Fluides, GAME ENGINE DEMO
#VERSION = "2.00"
;	
; Description : 	- Mets en place quelques fonctions simples et rapide permettant la simulation d'un fluide et de particules
;									- L'interface permets de tester ces fonctions rapidement
;									
; Détails & TODOs réalisés:
;									- Version 1.00
;									- Moteur de simulation
;									- Interface, clavier / souris
;									
;									- Version 2.00
;									- Ajout de sources flux / particules
;									- MAJ de l'interface : + de fluidité
;									- Multiples conditions limites : Boite / Libre
;									
;	Ajouts prévus :	
;									- Champ de particules de taille != du fluide
;									- Image à la place des particules
;									- Heigth map des vecteurs vitesse
;									- Tracé de lignes de flux continues
;									
;	Bug trouvés :		
;									- 
;									
; Bug corrigés :	
;									- 
;									
; Sources :
;									- Réalisé à partir de l'article de Jos Stam
;											"Real-Time Fluid Dynamics for Games"
;									- Plus de document du même auteur : 
;											http://www.dgp.toronto.edu/people/stam/reality/index.html
;	Compilateur :
;									- PureBasic 5.22LTS
;									- x86 / x64
;									- Window / Linux / Mac
;									- Pas d'usage d'API
;									
; Auteur : graph100 alias Kriek106
;}######################################


DisableDebugger

;{ initialisation

Structure POINT_d
	x.d
	y.d
EndStructure


Structure tableau
	Array tab.d(0, 0)
EndStructure

Macro Tableau_init(_adr_, _struct_)
	_adr_ = AllocateMemory(SizeOf(_struct_))
	InitializeStructure(_adr_, _struct_)
EndMacro

Macro Tableau_Free(_adr_, _struct_)
	ClearStructure(_adr_, _struct_)
	FreeMemory(_adr_)
EndMacro



Structure Fluide
	
	; Paramètres
	
	W.l
	H.l
	
	Viscosite.d
	
	; Calculs
	dim_w.l ; = w + 1 ; Dim 0 et n+1 sont là pour les conditions limites
	dim_h.l ; = h + 1
	max_wh.d ; max(W, H)
	
	; Tableaux des vitesses du fluide
	*u.tableau
	*v.tableau
	
	*u_prec.tableau
	*v_prec.tableau
	
EndStructure

Structure Densite
	diffusion.d ; taux de diffusion de la densité (entre 0 et 1)
	
	*densite.tableau
	*densite_prec.tableau
EndStructure


Structure Source_Vitesse
	Pos.POINT
	dir.POINT_d ; pixels / seconde
	
	vitesse.d ; indicatif, ne sert pas dans les calculs, mais pour affichage
EndStructure

Structure Source_Particule
	Pos.POINT
	
	Debit.d ; particules / seconde
EndStructure


Structure SIM_FL
	Fluide.Fluide
	Densite.Densite
	
	dt.d ; s entre chaque simulation
	
	List Source_Vitesses.Source_Vitesse()
	List Source_Particules.Source_Particule()
	
EndStructure




Procedure Fluide_Init(*obj.Fluide, Largeur.l, Hauteur.l, Viscosite.d)
	With *obj
		
		\W = Largeur
		\H = Hauteur
		
		If \W < \H
			\max_wh = \W
		Else
			\max_wh = \H
		EndIf
		
		\Viscosite = Viscosite
		
		\Dim_w = \w + 1
		\Dim_h = \h + 1
		
		Tableau_init(\u, tableau)
		Tableau_init(\v, tableau)
		
		Tableau_init(\u_prec, tableau)
		Tableau_init(\v_prec, tableau)
		
		Dim \u\tab(\Dim_w, \Dim_h)
		Dim \v\tab(\Dim_w, \Dim_h)
		Dim \u_prec\tab(\Dim_w, \Dim_h)
		Dim \v_prec\tab(\Dim_w, \Dim_h)
		
	EndWith
EndProcedure

Procedure Densite_Init(*obj.Densite, *fluide.Fluide, Diffusion.d)
	With *obj
		
		\diffusion = Diffusion
		
		Tableau_init(\densite, tableau)
		Tableau_init(\densite_prec, tableau)
		
		Dim \densite\tab(*fluide\Dim_w, *fluide\Dim_h)
		Dim \densite_prec\tab(*fluide\Dim_w, *fluide\Dim_h)
		
	EndWith
EndProcedure


Procedure.i AjouterSource_Flux(*obj.SIM_FL, x.l, y.l, dir_x.d, dir_y.d)
	Protected *new_vit.Source_Vitesse = AddElement(*obj\Source_Vitesses())
	
	*new_vit\Pos\x = x
	*new_vit\Pos\y =y
	
	*new_vit\dir\x = dir_x
	*new_vit\dir\y = dir_y
	
	*new_vit\vitesse = Sqr(*new_vit\dir\x * *new_vit\dir\x + *new_vit\dir\y * *new_vit\dir\y)
	
	ProcedureReturn *new_vit
EndProcedure

Procedure.i AjouterSource_Particules(*obj.SIM_FL, x.l, y.l, debit.d)
	Protected *new_part.Source_Particule = AddElement(*obj\Source_Particules())
	
	*new_part\Pos\x = x
	*new_part\Pos\y = y
	
	*new_part\Debit = debit
	
	ProcedureReturn *new_part
EndProcedure


;}


;{ Simulation

Procedure FS_SetBoundaryCondition_Boite(*obj.SIM_FL, MODE.l, Array x.d(2))
	With *obj
		
		; MODE = 0 : lorsque x() = dens()
		; MODE = 1 : lorsque x() = u()
		; MODE = 2 : lorsque x() = v()
		
		Protected i
		
		If MODE = 2
			For i = 1 To \Fluide\W
				
				x(i, 0) = - x(i, 1)
				x(i, \Fluide\dim_h) = - x(i, \Fluide\H)
				
			Next
		Else
			For i = 1 To \Fluide\W
				
				x(i, 0) = x(i, 1)
				x(i, \Fluide\dim_h) = x(i, \Fluide\H)
				
			Next
		EndIf
		
		If MODE = 1
			For i = 1 To \Fluide\H
				
				x(0, i) = - x(1, i)
				x(\Fluide\dim_w, i) = - x(\Fluide\W, i)
				
			Next
		Else
			For i = 1 To \Fluide\H
				
				x(0, i) = x(1, i)
				x(\Fluide\dim_w, i) = x(\Fluide\W, i)
				
			Next
		EndIf
		
		; Les coins
		x(0, 0) = 0.5 * (x(1, 0) + x(0, 1))
		x(0, \Fluide\dim_h) = 0.5 * (x(1, \Fluide\dim_h) + x(0, \Fluide\H))
		x(\Fluide\dim_w, 0) = 0.5 * (x(\Fluide\W, 0) + x(\Fluide\dim_w, 1))
		x(\Fluide\dim_w, \Fluide\dim_h) = 0.5 * (x(\Fluide\W, \Fluide\dim_h) + x(\Fluide\dim_w, \Fluide\H))
		
	EndWith
EndProcedure

Procedure FS_SetBoundaryCondition_Libre(*obj.SIM_FL, MODE.l, Array x.d(2))
	With *obj
		
		Protected i
		
		For i = 1 To \Fluide\W
			
			x(i, 0) = x(i, 1)
			x(i, \Fluide\dim_h) = x(i, \Fluide\H)
			
		Next
		
		For i = 1 To \Fluide\H
			
			x(0, i) = x(1, i)
			x(\Fluide\dim_w, i) = x(\Fluide\W, i)
			
		Next
		
		; Les coins
		x(0, 0) = 0.5 * (x(1, 0) + x(0, 1))
		x(0, \Fluide\dim_h) = 0.5 * (x(1, \Fluide\dim_h) + x(0, \Fluide\H))
		x(\Fluide\dim_w, 0) = 0.5 * (x(\Fluide\W, 0) + x(\Fluide\dim_w, 1))
		x(\Fluide\dim_w, \Fluide\dim_h) = 0.5 * (x(\Fluide\W, \Fluide\dim_h) + x(\Fluide\dim_w, \Fluide\H))
		
	EndWith
EndProcedure


Prototype FS_SetBoundaryCondition(*obj.SIM_FL, MODE.l, Array x.d(2))
Global FS_SetBoundaryCondition.FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()




Procedure FS_LinSolve(*obj.SIM_FL, MODE.l, Array x.d(2), Array x0.d(2), a.d, c.d)
	With *obj
		
		Protected.l i, j, k
		
		For k = 0 To 20
			
			For i = 1 To \Fluide\W
				For j = 1 To \Fluide\H
					
					x(i, j) = (x0(i, j) + a * (x(i-1, j) + x(i+1, j) + x(i, j-1) + x(i, j+1))) / c
					
				Next
			Next
			
			FS_SetBoundaryCondition(*obj, MODE, x())
			
		Next
		
	EndWith
EndProcedure

Procedure FS_AddSource(*obj.SIM_FL, Array x.d(2), Array source.d(2))
	With *obj
		
		Protected i, j
		
		
		For i = 0 To \Fluide\dim_w
			For j = 0 To \Fluide\dim_h
				
				x(i, j) = x(i, j) + \dt * source(i, j)
				
			Next
		Next
		
	EndWith
EndProcedure


Procedure FS_Diffusion(*obj.SIM_FL, MODE.l, Array x.d(2), Array x0.d(2), diffusion.d, dt.d)
	With *obj
		
		Protected.d a = dt * diffusion * \Fluide\W * \Fluide\H
		
		FS_LinSolve(*obj, MODE, x(), x0(), a, 1 + 4  * a)
		
	EndWith
EndProcedure

Procedure FS_Advection(*obj.SIM_FL, MODE.l, Array d.d(2), Array d0.d(2), Array u.d(2), Array v.d(2), dt.d)
	With *obj
		
		Protected.l i, j, i0, j0, i1, j1
		Protected.d x, y, s0, t0, s1, t1, dt0_u, dt0_v
		
		; dt0 = dt * N ; mais ici j'ai pris un rectangle et non pas un carré !
		dt0_u = dt * \Fluide\W
		dt0_v = dt * \Fluide\H
		
		
		For i = 1 To \Fluide\W
			For j = 1 To \Fluide\H
				
				x = i - dt0_u * u(i, j)
				y = j - dt0_v * v(i, j)
				
				If x < 0.5 : x = 0.5 : EndIf
				If x > \Fluide\W + 0.5 : x = \Fluide\W + 0.5 : EndIf
				i0 = Round(x, #PB_Round_Down)
				i1 = i0 + 1
				
				If y < 0.5 : y = 0.5 : EndIf
				If y > \Fluide\H + 0.5 : y = \Fluide\H + 0.5 : EndIf
				j0 = Round(y, #PB_Round_Down)
				j1 = j0 + 1
				
				s1 = x - i0
				s0 = 1 - s1
				t1 = y - j0
				t0 = 1 - t1
				
				d(i, j) = s0 * (t0 * d0(i0, j0) + t1 * d0(i0, j1)) + s1 * (t0 * d0(i1, j0) + t1 * d0(i1, j1))
				
			Next
		Next
		
		FS_SetBoundaryCondition(*obj, MODE, d())
		
		
	EndWith
EndProcedure

Procedure FS_Projection(*obj.SIM_FL, Array u.d(2), Array v.d(2), Array p.d(2), Array div.d(2))
	With *obj
		
		Protected.l i, j
		
		For i = 1 To \Fluide\W
			For j = 1 To \Fluide\H
				
				; ici on change le /N qui apparait dans le code original, pour voir comment ça se comporte avec un rectangle
; 				div(i, j) = -0.5 * ((u(i+1, j) - u(i-1, j)) / *obj\Fluide\W + (v(i, j+1) - v(i, j-1)) / *obj\Fluide\H)
				div(i, j) = -0.5 * ((u(i+1, j) - u(i-1, j) + v(i, j+1) - v(i, j-1)) / *obj\Fluide\max_wh)
				
				p(i, j) = 0
			Next
		Next
		
		FS_SetBoundaryCondition(*obj, 0, div())
		FS_SetBoundaryCondition(*obj, 0, p())
		
		
		FS_LinSolve(*obj, 0, p(), div(), 1, 4) ; boom !! prend ça !
		
		
		For i = 1 To \Fluide\W
			For j = 1 To \Fluide\H
				
				u(i, j) = u(i, j) - 0.5 * \Fluide\W * (p(i+1, j) - p(i-1, j))
				v(i, j) = v(i, j) - 0.5 * \Fluide\H * (p(i, j+1) - p(i, j-1))
				
			Next
		Next
		
		FS_SetBoundaryCondition(*obj, 1, u())
		FS_SetBoundaryCondition(*obj, 2, v())
		
	EndWith
EndProcedure


Procedure Fluide_Sim_Densite(*obj.SIM_FL)
	
	FS_AddSource(*obj, *obj\Densite\densite\tab(), *obj\Densite\densite_prec\tab())
	
	Swap *obj\Densite\densite_prec, *obj\Densite\densite
	FS_Diffusion(*obj, 0, *obj\Densite\densite\tab(), *obj\Densite\densite_prec\tab(), *obj\Densite\diffusion, *obj\dt)
	
	Swap *obj\Densite\densite_prec, *obj\Densite\densite
	FS_Advection(*obj, 0, *obj\Densite\densite\tab(), *obj\Densite\densite_prec\tab(), *obj\Fluide\u\tab(), *obj\Fluide\v\tab(), *obj\dt)
	
EndProcedure

Procedure Fluide_Sim_Velocite(*obj.SIM_FL)
	
	FS_AddSource(*obj, *obj\Fluide\u\tab(), *obj\Fluide\u_prec\tab())
	FS_AddSource(*obj, *obj\Fluide\v\tab(), *obj\Fluide\v_prec\tab())
	
	Swap *obj\Fluide\u_prec, *obj\Fluide\u
	Swap *obj\Fluide\v_prec, *obj\Fluide\v
	
	FS_Diffusion(*obj, 1, *obj\Fluide\u\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\Viscosite, *obj\dt)
	FS_Diffusion(*obj, 2, *obj\Fluide\v\tab(), *obj\Fluide\v_prec\tab(), *obj\Fluide\Viscosite, *obj\dt)
	
	FS_Projection(*obj, *obj\Fluide\u\tab(), *obj\Fluide\v\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab())
	
	Swap *obj\Fluide\u_prec, *obj\Fluide\u
	Swap *obj\Fluide\v_prec, *obj\Fluide\v
	
	FS_Advection(*obj, 1, *obj\Fluide\u\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab(), *obj\dt)
	FS_Advection(*obj, 2, *obj\Fluide\v\tab(), *obj\Fluide\v_prec\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab(), *obj\dt)
	
	FS_Projection(*obj, *obj\Fluide\u\tab(), *obj\Fluide\v\tab(), *obj\Fluide\u_prec\tab(), *obj\Fluide\v_prec\tab())
	
EndProcedure


;}



Define Var.SIM_FL : InitializeStructure(Var, SIM_FL)
Define souris.POINT, souris_case.POINT, *Obj_sous_souris, Type_sous_souris.l
Define mouse.POINT, mouse_old.POINT

Enumeration 1
	#OBJ_Source_VITESSE
	#OBJ_Source_PARTICULE
EndEnumeration


SIMUL = #True

Macro INIT_SIM
	Fluide_Init(Var\fluide, 100, 100, 0)
	
	Densite_Init(Var\Densite, Var\Fluide, 0.0)
EndMacro


;{ scénario : la chandelle

INIT_SIM
AjouterSource_Flux(Var, Var\Fluide\dim_w >> 1 - 1, Var\Fluide\dim_h - 5, 0, -50)
AjouterSource_Particules(Var, Var\Fluide\dim_w >> 1, Var\Fluide\dim_h - 20, 1800 / 20)

;}


;{ Démo


;{ fenetre

width = 7
width_sur2moins1 = width >> 1 - 1
width_sur2 = width >> 1
width_moins1 = width - 1

draw_info_h = (Var\Fluide\dim_h + 1) * width +1
draw_info_w = (Var\Fluide\dim_w +1) * width +1

DRAW_CASE = #False
DRAW_VITESSE = #True
DRAW_PARTICULES = #True
DRAW_SOURCES = #True

Tps_Loop_mini.d = 0.040 ; s


OpenWindow(0, 0, 0, draw_info_w, draw_info_h + 200, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), #PB_Canvas_Keyboard)

SetActiveGadget(0)

;}

time = ElapsedMilliseconds()

Repeat
	
	FLAG_MOUSE_RIGHT = #False
	FLAG_MOUSE_LEFT = #False
	
	Repeat
		event = WindowEvent()
		
		;{ event
		
		If event = #PB_Event_Gadget And EventGadget() = 0
			
			;{ souris
			
			souris\x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
			souris\y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
			
			souris_case\x = souris\x / width
			souris_case\y = souris\y / width
			
			If souris_case\x < 1 : souris_case\x = 1 : EndIf
			If souris_case\x > Var\Fluide\W : souris_case\x = Var\Fluide\W :EndIf
			If souris_case\y < 1 : souris_case\y = 1 : EndIf
			If souris_case\y > Var\Fluide\H : souris_case\y = Var\Fluide\H :EndIf
			
			;}
			
			
			;{ Touche D
			If GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_D
				
				If *Obj_sous_souris And Type_sous_souris = #OBJ_Source_PARTICULE
					ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
					
					With var\Source_Particules()
						
						x = souris\x - (\Pos\x  * width + width_sur2)
						y = souris\y - (\Pos\y  * width + width_sur2)
						
						\Debit = Sqr(x * x + y * y)
						
					EndWith
					
				ElseIf *Obj_sous_souris And Type_sous_souris = #OBJ_Source_VITESSE
					ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
					
					With var\Source_Vitesses()
						
						\dir\x = souris\x - (\Pos\x  * width + width_sur2)
						\dir\y = souris\y - (\Pos\y  * width + width_sur2)
						
						\vitesse = Sqr(\dir\x * \dir\x + \dir\y * \dir\y)
					EndWith
					
				EndIf
				
			EndIf
			;}
			
			;{ Touche E
			If GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_E
				
				If *Obj_sous_souris And Type_sous_souris = #OBJ_Source_PARTICULE
					ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
					
					With var\Source_Particules()
						
						\Pos\x = souris_case\x
						\Pos\y = souris_case\y
						
					EndWith
					
				ElseIf *Obj_sous_souris And Type_sous_souris = #OBJ_Source_VITESSE
					ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
					
					With var\Source_Vitesses()
						
						\Pos\x = souris_case\x
						\Pos\y = souris_case\y
						
					EndWith
					
				EndIf
				
			EndIf
			;}
			
			If EventType() = #PB_EventType_KeyUp
				
				;{ Key
				
				If GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_Escape
					event = #PB_Event_CloseWindow
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_C
					
					INIT_SIM
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_Delete
					
					If *Obj_sous_souris And Type_sous_souris = #OBJ_Source_PARTICULE
						ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
						DeleteElement(var\Source_Particules())
						
						*Obj_sous_souris = 0
						Type_sous_souris = 0
						
					ElseIf *Obj_sous_souris And Type_sous_souris = #OBJ_Source_VITESSE
						ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
						DeleteElement(var\Source_Vitesses())
						
						*Obj_sous_souris = 0
						Type_sous_souris = 0
						
					EndIf
					
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_X
					
					; ajouter ici les autres conditions si besoin
					If FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
						FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Libre()
					ElseIf FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Libre()
						FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
					EndIf
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_V
					
					If DRAW_VITESSE : DRAW_VITESSE = #False
					Else : DRAW_VITESSE = #True
					EndIf
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_G
					
					If DRAW_CASE : DRAW_CASE = #False
					Else : DRAW_CASE = #True
					EndIf
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_P
					
					If DRAW_PARTICULES : DRAW_PARTICULES = #False
					Else : DRAW_PARTICULES = #True
					EndIf
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_S
					
					If DRAW_SOURCES : DRAW_SOURCES = #False
					Else : DRAW_SOURCES = #True
					EndIf
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_Space
					
					If SIMUL = #True : SIMUL = #False
					Else : SIMUL = #True
					EndIf
					
				ElseIf GetGadgetAttribute(0, #PB_Canvas_Key) = #PB_Shortcut_N
					
					If EDIT = #True : EDIT = #False
					Else : EDIT = #True
					EndIf
					
				EndIf
				
				;}
				
			ElseIf EventType() = #PB_EventType_LeftButtonUp
				;{ Ajout source permanente de vitesse
				
				
				;{ détection d'objet sous la souris
				
				*Obj_sous_souris = 0
				Type_sous_souris = 0
				
				; vitesse
				ForEach var\Source_Vitesses()
					With var\Source_Vitesses()
						
						If \Pos\x = souris_case\x And \Pos\y = souris_case\y
							*Obj_sous_souris = Var\Source_Vitesses()
							
							Type_sous_souris = #OBJ_Source_VITESSE
						EndIf
						
					EndWith
				Next
				
				; particules
				ForEach var\Source_Particules()
					With var\Source_Particules()
						
						If \Pos\x = souris_case\x And \Pos\y = souris_case\y
							*Obj_sous_souris = Var\Source_Particules()
							
							Type_sous_souris = #OBJ_Source_PARTICULE
						EndIf
						
					EndWith
				Next
				
				;}
				
				
				If EDIT And *Obj_sous_souris = 0
					*Obj_sous_souris = AjouterSource_Flux(Var, souris_case\x, souris_case\y, 20, 0)
					Type_sous_souris = #OBJ_Source_VITESSE
				EndIf
				
				;}
				
			ElseIf EventType() = #PB_EventType_RightButtonUp
				;{ Ajout source permanente de particules
				
				If EDIT
					*Obj_sous_souris = AjouterSource_Particules(Var, souris_case\x, souris_case\y, 10)
					Type_sous_souris = #OBJ_Source_PARTICULE
				EndIf
				
				;}
				
			EndIf
			
			;{ AJOUT à la souris
			If EDIT = #False
				If GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_RightButton = #PB_Canvas_RightButton
					FLAG_MOUSE_RIGHT = #True
				EndIf
				If GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton = #PB_Canvas_LeftButton
					FLAG_MOUSE_LEFT = #True
				Else
					REINIT = #True
					
				EndIf
			EndIf
			;}
			
		EndIf
		;}
		
	Until event = 0 Or event = #PB_Event_CloseWindow
	
	
	;{ mise à jour du delta de temps et stabilisation des FPS
	
	Var\dt = (ElapsedMilliseconds() - time) / 1000
	
	If var\dt < Tps_Loop_mini
		Delay(1000 * (Tps_Loop_mini - Var\dt))
	EndIf
	
	Var\dt = (ElapsedMilliseconds() - time) / 1000 ; on reprend le temps total de la boucle, delay compris
	time = ElapsedMilliseconds()
	
	;}
	
	
	;{ SIMULATION
	
	If SIMUL
		
		tps = ElapsedMilliseconds()
		
		; reset des anciens tableaux
		Dim Var\Densite\densite_prec\tab(Var\Fluide\dim_w, Var\Fluide\dim_h)
		Dim Var\Fluide\u_prec\tab(Var\Fluide\dim_w, Var\Fluide\dim_h)
		Dim Var\Fluide\v_prec\tab(Var\Fluide\dim_w, Var\Fluide\dim_h)
		
		If EDIT = #False
			
			;{ ajout a la souris de particules
			If FLAG_MOUSE_RIGHT
				var\Densite\densite_prec\tab(souris_case\x, souris_case\y) = 10000 * Var\dt
			EndIf	
			;}
			
			;{ ajout a la souris de vitesse
			If FLAG_MOUSE_LEFT
				If REINIT
					REINIT = #False
					
					mouse_old = souris
				EndIf
				
				mouse\x = (souris\x - mouse_old\x) * 50
				mouse\y = (souris\y - mouse_old\y) * 50
				
				mouse_old = souris
				
				var\Fluide\u_prec\tab(souris_case\x, souris_case\y) = mouse\x
				var\Fluide\v_prec\tab(souris_case\x, souris_case\y) = mouse\y
			EndIf	
			;}
			
			;{ Ajout des sources de particules
			
			ForEach Var\Source_Particules()
				With var\Source_Particules()
					var\Densite\densite_prec\tab(\Pos\x, \Pos\y) = 20*\Debit * Var\dt
				EndWith
			Next
			
			;}
			
			;{ Ajout des sources de vitesse
			
			ForEach Var\Source_Vitesses()
				With var\Source_Vitesses()
					var\Fluide\u_prec\tab(\Pos\x, \Pos\y) = \dir\x
					var\Fluide\v_prec\tab(\Pos\x, \Pos\y) = \dir\y
				EndWith
			Next
			
			;}
			
		EndIf
		
		;For i = 1 To 10
		; Simulation
		Fluide_Sim_Velocite(Var)
		Fluide_Sim_Densite(Var)
		;Next
		
		tps = ElapsedMilliseconds() - tps
		
	EndIf
	
	
	;}
	
	
	;{ Affichage
	
	If StartDrawing(CanvasOutput(0))
		
		Box(0, 0, OutputWidth(), OutputHeight(), 0)
		
		;{ particules / Grille / vitesse
		If DRAW_PARTICULES
			; dessin de la densité
			
			NB_particules.d = 0
			
			For i = 0 To Var\Fluide\dim_w
				For j = 0 To Var\Fluide\dim_h
					x = i * width + width >> 1
					y = j * width + width >> 1
					
					c.d = 255*(Var\Densite\densite\tab(i, j))
					
					NB_particules + Var\Densite\densite\tab(i, j)
					
					If c > 255 : c = 255 : EndIf
					
; 					Box(x - width_sur2moins1, y - width_sur2moins1, width_moins1, width_moins1, RGB(c, c, c))
					Box(x - width_sur2moins1, y - width_sur2moins1, width, width, RGB(c, c, c))
				Next
			Next
		EndIf
		
		If DRAW_CASE
			; grille
			For i = 0 To Var\Fluide\dim_w +1
				Line(i * width, 0, 1, draw_info_h, $003F00)
			Next
			For i = 0 To Var\Fluide\dim_h +1
				Line(0, i * width, draw_info_w, 1, $003F00)
			Next
		EndIf
		
		
		If DRAW_VITESSE
			; dessin des vecteur vitesse
			
			For i = 0 To Var\Fluide\dim_w
				For j = 0 To Var\Fluide\dim_h
					x = i * width + width >> 1
					y = j * width + width >> 1
					
					LineXY(x, y, x + Var\Fluide\u\tab(i, j) * 10, y + Var\Fluide\v\tab(i, j) * 10, #Red)
				Next
			Next
		EndIf
		;}
		
		;{ sources
		If DRAW_SOURCES Or EDIT
			
			; vitesse
			ForEach var\Source_Vitesses()
				With var\Source_Vitesses()
					x = \Pos\x  * width + width_sur2
					y = \Pos\y * width + width_sur2
					
					Circle(x, y, width_sur2, $007AFF)
					
					If *Obj_sous_souris = Var\Source_Vitesses()
						DrawingMode(#PB_2DDrawing_Outlined)
						
						Circle(x, y, width_sur2 + 3, #Blue)
						Circle(x, y, width_sur2 + 2, #Blue)
						
						DrawingMode(#PB_2DDrawing_Default)
					EndIf
					
					
					LineXY(x, y, x + \dir\x, y + \dir\y, #Green)
				EndWith
			Next
			
			
			; particules
			ForEach var\Source_Particules()
				With var\Source_Particules()
					x = \Pos\x  * width + width_sur2
					y = \Pos\y * width + width_sur2
					
					Circle(x, y, width_sur2, #White)
					
					If *Obj_sous_souris = Var\Source_Particules()
						DrawingMode(#PB_2DDrawing_Outlined)
						
						Circle(x, y, width_sur2 + 3, #Blue)
						Circle(x, y, width_sur2 + 2, #Blue)
						
						DrawingMode(#PB_2DDrawing_Default)
					EndIf
					
					DrawingMode(#PB_2DDrawing_Outlined)
					
					Circle(x, y, \Debit, $007AFF)
					
					DrawingMode(#PB_2DDrawing_Default)
					
				EndWith
			Next
			
		EndIf
		;}
		
		;{ INFO
		
		
		If EDIT
			Circle(souris_case\x  * width + width_sur2, souris_case\y * width + width_sur2, width_sur2, #Blue)
		EndIf
		
		; info
		
		If SIMUL
			DrawText(10, draw_info_h + 5, "Simulation : En cours", #White, 0)
		Else
			DrawText(10, draw_info_h + 5, "Simulation : En pause", #White, 0)
		EndIf
		
		If EDIT
			DrawText(200, draw_info_h + 5, "EDITION des SOURCES", #White, 0)
		Else
			; DrawText(200, draw_info_h + 5, "", #White, 0)
		EndIf
		
		DrawText(10, draw_info_h + 25, "dt = " + StrD(Var\dt, 3), #White, 0)
		DrawText(100, draw_info_h + 25, "NB_part = " + StrD(NB_particules, 3), #White, 0)
		
		DrawText(10, draw_info_h + 50, "[Souris Gauche] ajouter du flux", #White, 0)
		DrawText(10, draw_info_h + 70, "[Souris Droite] ajouter des particules", #White, 0)
		DrawText(10, draw_info_h + 90, "[N] MODE Sources permanentes", #White, 0)
		DrawText(10, draw_info_h + 110, "[Clic sur source] Selectionne une source", #White, 0)
		DrawText(10, draw_info_h + 130, "[SUPPR] Supprime une source", #White, 0)
		DrawText(10, draw_info_h + 150, "[D] Modifier le niveau des sources", #White, 0)
		DrawText(10, draw_info_h + 170, "[E] Déplacer une sources", #White, 0)
		
		DrawText(280, draw_info_h + 30, "[C] réinitialiser", #White, 0)
		DrawText(280, draw_info_h + 50, "[ESPACE] pause", #White, 0)
		DrawText(280, draw_info_h + 70, "[ECHAP] quitter", #White, 0)
		
		DrawText(280, draw_info_h + 90, "[G] Affiche la grille", #White, 0)
		DrawText(280, draw_info_h + 110, "[P] Affiche les particules", #White, 0)
		DrawText(280, draw_info_h + 130, "[V] Affiche les vecteurs vitesse", #White, 0)
		DrawText(280, draw_info_h + 130, "[S] Affiche les Sources", #White, 0)
		DrawText(280, draw_info_h + 150, "[X] Change les conditions aux limites", #White, 0)
		
		DrawText(500, draw_info_h + 10, "INFO Object", #White, 0)
		
		If *Obj_sous_souris
			If Type_sous_souris = #OBJ_Source_PARTICULE
				DrawText(500, draw_info_h + 35, "Type : Source de Particule", #White, 0)
				
				ChangeCurrentElement(var\Source_Particules(), *Obj_sous_souris)
				DrawText(500, draw_info_h + 55, "Débit : " + StrD(var\Source_Particules()\Debit * 20, 3), #White, 0)
				
			Else
				DrawText(500, draw_info_h + 35, "Type : Source de Flux", #White, 0)
				
				ChangeCurrentElement(var\Source_Vitesses(), *Obj_sous_souris)
				DrawText(500, draw_info_h + 55, "Vitesse : " + StrD(var\Source_Vitesses()\vitesse, 3), #White, 0)
			EndIf
		Else
			DrawText(500, draw_info_h + 30, "Pas de sélection", #White, 0)
		EndIf
		
		If FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Boite()
			DrawText(500, draw_info_h + 80, "Condition Limite : Boite", #White, 0)
		ElseIf FS_SetBoundaryCondition = @FS_SetBoundaryCondition_Libre()
			DrawText(500, draw_info_h + 80, "Condition Limite : Libre", #White, 0)
		EndIf
		
		
		;}
		
		StopDrawing()
	EndIf
	
	;}
	
Until event = #PB_Event_CloseWindow


;}

End
Dernière modification par graph100 le lun. 16/juin/2014 14:11, modifié 4 fois.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Dynamique des Fluides, Simulation

Message par SPH »

IMPRESSIONNANT 8O
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Dynamique des Fluides, Simulation

Message par Backup »

oui , tres impressionnant :)

plus qu'a mettre un colorant, et voir :)
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Re: Dynamique des Fluides, Simulation

Message par Frenchy Pilou »

Excellent! 8)

Le début d'une grande vague! 8)

Image
Est beau ce qui plaît sans concept :)
Speedy Galerie
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Dynamique des Fluides, Simulation

Message par Ar-S »

Très fluide si je puis dire ;) bravo.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Dynamique des Fluides, Simulation

Message par SPH »

maintenant, va falloir utiliser de la peinture liquide :twisted: :twisted: :twisted: :?

Graph100, tu l'as codé en combien de temps ? :arrow: 8O
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Dynamique des Fluides, Simulation

Message par graph100 »

Tout ce soir, 4h pour poster, puis ensuite je suis dessus depuis encore 3h pour ajouter des truc rigolos :lol: (sources de vitesse / particules)
En revanche, hier j'ai commencé à lire le document qui expose l'idée et aussi faire fonctionner le code C (installer les lib :twisted: etc...) pour avoir une meilleur idée du bouzin.

La couleur ça viendras plus tard, en informatique on commence toujours en noir et blanc :mrgreen:
J'ajouterais que même si on voit les "zones" minimum de modélisation, on peut lisser avec une formule très simple pour obtenir un beau résultat.

Et pour pouvoir tenir la comparaison avec la vitesse de Verve, il faudrait accélérer le prog avec la carte graphique, ce que je ne sais pas faire...
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Dynamique des Fluides, Simulation

Message par graph100 »

Deuxième version : (Dans le 1er post, en 1er, je garde l'autre pour archive)

- ajout de sources permanente de flux (mouvement) / particules
- mise à jour du reste et des infos
- petit scénario mis en place au lancement pour faire une jolie démo :D

après quelques instants, et [V] pour virer les vecteurs vitesse :

Image

Ce qui prend du temps, c'est que j'en perd énormément à jouer avec le prog :mrgreen:
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
Huitbit
Messages : 939
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: Dynamique des Fluides, Simulation

Message par Huitbit »

Impressionnant de fluidité 8O (même en mode debug ) !

Chapeau !
Elevé au MSX !
Avatar de l’utilisateur
GallyHC
Messages : 1703
Inscription : lun. 17/déc./2007 12:44

Re: Dynamique des Fluides, Simulation

Message par GallyHC »

Bonjour,

Vraiment sympa comme source.

GallyHC
Dernière modification par GallyHC le lun. 16/juin/2014 7:49, modifié 1 fois.
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Dynamique des Fluides, Simulation

Message par Backup »

@graph100 , franchement ça le fait grave :)

par contre ne te lance pas dans une ribambelle de raccourcis clavier
c'est le principale defaut de Verve ... :)
Dernière modification par Backup le lun. 16/juin/2014 11:50, modifié 1 fois.
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Dynamique des Fluides, Simulation

Message par graph100 »

Merci :wink: , c'est vrai que c'est vraiment fun a dev ce truc !
Dobro a écrit :par contre ne te lance pas dans une ribambelle de raccourcis clavier
c'est le principale defaut de Verve ... :)
héhé, c'est pour ça que je les ai indiqué en dessous.
Pour une version de démo, je préfère ne pas me prendre la tête avec l'interface !

Et puis mon but n'est pas de refaire Verve !

@Huitbit : même si tu compiles avec le débogueur, j'ai mis le flag DisableDebugger tout au début :lol:
C'est le genre typique de programme qui rame avec le débogueur ! -> parcourt de tableau dans tout les sens et en permanence...
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Re: Dynamique des Fluides, Simulation

Message par Frenchy Pilou »

Très cool! 8)
Par contre il n'y a pas de bouton de ré-intialisation quand l'écran est devenu tout blanc par exemple! :)
Est beau ce qui plaît sans concept :)
Speedy Galerie
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Dynamique des Fluides, Simulation

Message par graph100 »

Si : [C]
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Fred
Site Admin
Messages : 2648
Inscription : mer. 21/janv./2004 11:03

Re: Dynamique des Fluides, Simulation

Message par Fred »

Sympa ! :)
Répondre