Folyékony anyagok Füstszerű elenségek Felhők Festékek
Sebesség (vektormező) x = (x y) ozícó = (v) sebesség T dő (x t) = ((x t) v(x t)) Kocka rács
Clade Naver és George Gabrel Stokes Folyékony anyagok mozgása áramlása Ala feltevések Az anyagban felléő feszültség két összetevőe A sebesség gradensével arányos dffúzó Nyomás összetevő
Számos fzka elenség leírására alkalmas Időárás Folyadékok áramlása nem kör keresztmetszetű csatornákban Reülőgéek szárnya körül felléő áramlás Szlárd testek folyékony anyagokon keresztül mozgása (l. a csllagok galaxsokon belül leírt mozgása) Összekacsolható a Maxwell egyenletekkel (magnetohdrodnamka)
Tsztán elmélet értelemben s fontos Nncs bzonyítva a három dmenzós érvényesség A létezés és smaság robléma annyra fontos hogy a Clay Mathematcs Insttte az évezred hét legfontosabb matematka roblémá között tarta számon. A megoldásra egymlló dolláros díat tűztek k
1.) t ( ) 1 2 F 2.) 0 : sűrűség : vszkoztás F : Külső erők Összenyomhatatlan homogén folyadékok
Advekcó ( ) Előre haladás szállítás Bármlyen mennységet Saát vektormezőt s
Nyomás 1 Az erő nem hrtelen áramlk végg a folyadékon A moleklák ütköznek nyomás keletkezk Gyorslást (sebességváltozást) eredményez
Dffúzó 2 A különböző folyadékok különbözőkéen mozognak: vannak sűrűbbek és vannak folyékonyabbak Vszkoztás: mennyre ellenálló a folyadék az áramlásra Ez az ellenállás sebesség dffúzót okoz
Külső erők F Lehetnek lokálsak vagy globálsak (l gravtácó)
2 1 1 1 1 2 ) ( 4 x y x y x 2 2 1 1 1 1 y v x y v v x 2 2 1 1 1 1 2 2 2 2 2 y x 2 1 1 2 1 1 ) ( 2 ) ( 2 y x Oerátor Defnícó Véges dfferenca alak Gradens Dvergenca Lalace
3 egyenlet: v Analtks megoldás rtkán és csak egyszerű esetekben található Nmerks módszerek nkrementáls megoldás Ha anmácót szeretnénk az dő nkrementálás még ól s ön A roblémát ksebb léésekre bontk (Stam J. 1999. "Stable Flds." In Proceedngs of SIGGRAPH 1999)
(Bármely vektor felbontható bázsvektorok súlyozott összegére) Bármely vektormező felbontható vektormezők összegére : w 0
1.) t ( ) 1 2 F 2.) 0 W w
w w w w 2 2 0 / ) ( / Posson egyenlet ) ( 2 b x
S( ) P F D A( ) Proekcó Külső erők Dffúzó Advekcó
t t t r t t r ) ( ) ( ) ( Eler módszer előreléés: Nem stabl (és shaderből nehezen végrehatható) A megoldás a vsszaléés: ) ) ( ( ) ( t t t x x q t t x q
Exlct megoldás: Nem stabl! Imlct megoldás: t 2 ) ( ) ( ) ( 2 t x t t x t t x ) ( ) ( ) ( 2 t x t t x t I Posson egyenlet ) ( 2 b x
w w 2 Posson egyenlet ( 2 x b )
Iteratív megoldás kndlnk egy kezdet állaotból és folyamatosan fnomítk alakú egyenlet Ax b Nálnk A a Lalace oerátor A legegyszerűbb megoldás a Jacob terácó
k k k k k b x x x x x ) ( 1 ) ( 1 ) ( 1 ) ( 1 1) ( Dffúzó Nyomás x sebesség () nyomás() b sebesség() sebesség dvergencáa -1.0 0.25 t 1 ) (4 1
Véges tartományon számítnk kellenek határfeltételek Ha az anyagot a szmlált tartományba zárk (falakkal vesszük körül) a sebességre és a nyomásra a feltételek: Sebesség: a határokon a sebesség nlla (no-sl feltétel) Nyomás: a határokon a nyomás változása nlla (Nemann feltétel)
A szmlácó és a dszkretzálás nmerks hbáa elmossa a mozgás bzonyos részletet a fnom örvényeket Ezeket csalk vssza: ( crl o.) f vc ( ) x
A mennységeket 2D tömbökben tárolk Mvel a számítások során szomszédosság nformácók kellenek néhány mennységet dla bfferben kell tároln (PING-PONG) A tömbök frssítését az OenCL kernelek végzk Az egyes számítás léésekhez külön külön kernelek szükségesek A megelenítés egyszerű kéernyőre razolás Kernel függvények...(folyt)
kernel vod advecton(const nt grdresolton global float2* ntveloctybffer global float2* ottveloctybffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton 1){ } float2 velocty = ntveloctybffer[d.x + d.y * grdresolton]; float2 = (float2)((float)d.x - dt * velocty.x (float)d.y - dt * velocty.y); ottveloctybffer[d.x + d.y * grdresolton] = getbl( grdresolton ntveloctybffer); } else{ //határfeltételek f(d.x == 0) ottveloctybffer[d.x + d.y * grdresolton] = - ntveloctybffer[d.x + 1 + d.y * grdresolton];... }
kernel vod dvergence(const nt grdresolton global float2* veloctybffer global float* dvergencebffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton - 1){ } float2 vl = veloctybffer[d.x - 1 + d.y * grdresolton]; float2 vr = veloctybffer[d.x + 1 + d.y * grdresolton]; float2 vb = veloctybffer[d.x + (d.y - 1) * grdresolton]; float2 vt = veloctybffer[d.x + (d.y + 1) * grdresolton]; dvergencebffer[d.x + d.y * grdresolton] = 0.5f * ((vr.x - vl.x) + (vt.y - vb.y)); } else{ dvergencebffer[d.x + d.y * grdresolton] = 0.0f; }
kernelvod ressrejacob(const nt grdresolton global float* ntpressrebffer global float* ottpressrebffer global float* dvergencebffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton - 1){ } float alha = -1.0f; float beta = 0.25f; float vl = ntpressrebffer[d.x - 1 + d.y * grdresolton]; float vr = ntpressrebffer[d.x + 1 + d.y * grdresolton]; float vb = ntpressrebffer[d.x + (d.y - 1) * grdresolton]; float vt = ntpressrebffer[d.x + (d.y + 1) * grdresolton]; float dvergence = dvergencebffer[d.x + d.y * grdresolton]; ottpressrebffer[d.x + d.y * grdresolton] = (vl + vr + vb + vt + alha * dvergence) * beta; }else{ //határfeltételek f(d.x == 0) ottpressrebffer[d.x + d.y * grdresolton] = ntpressrebffer[d.x + 1 + d.y * grdresolton];...}
kernel vod roecton(const nt grdresolton global float2* ntveloctybffer global float* ressrebffer global float2* ottveloctybffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton - 1){ } float L = ressrebffer[d.x - 1 + d.y * grdresolton]; float R = ressrebffer[d.x + 1 + d.y * grdresolton]; float B = ressrebffer[d.x + (d.y - 1) * grdresolton]; float T = ressrebffer[d.x + (d.y + 1) * grdresolton]; float2 velocty = ntveloctybffer[d.x + d.y * grdresolton]; ottveloctybffer[d.x + d.y * grdresolton] = velocty (float2)(r - L T - B); } else {//határfeltételek f(d.x == 0) ottveloctybffer[d.x + d.y * grdresolton] = -ntveloctybffer[d.x + 1 + d.y * grdresolton];... }
kernel vod dffson(const nt grdresolton global float2* ntveloctybffer global float2* ottveloctybffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); float vscosty = 0.01f; float alha = 1.0f / (vscosty * dt); float beta = 1.0f / (4.0f + alha); f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton - 1){ float2 vl = ntveloctybffer[d.x - 1 + d.y * grdresolton]; float2 vr = ntveloctybffer[d.x + 1 + d.y * grdresolton]; float2 vb = ntveloctybffer[d.x + (d.y - 1) * grdresolton]; float2 vt = ntveloctybffer[d.x + (d.y + 1) * grdresolton]; float2 velocty = ntveloctybffer[d.x + d.y * grdresolton]; ottveloctybffer[d.x + d.y * grdresolton] = (vl + vr + vb + vt + alha * velocty) * beta; } else { ottveloctybffer[d.x + d.y * grdresolton] = ntveloctybffer[d.x + d.y * grdresolton]; }}
kernel vod vortcty(const nt grdresolton global float2* veloctybffer global float* vortctybffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton 1){ } float2 vl = veloctybffer[d.x - 1 + d.y * grdresolton]; float2 vr = veloctybffer[d.x + 1 + d.y * grdresolton]; float2 vb = veloctybffer[d.x + (d.y - 1) * grdresolton]; float2 vt = veloctybffer[d.x + (d.y + 1) * grdresolton]; vortctybffer[d.x + d.y * grdresolton] = (vr.y - vl.y) - (vt.x - vb.x); } else{ vortctybffer[d.x + d.y * grdresolton] = 0.0f; }
kernel vod addvortcty(const nt grdresolton global float* vortctybffer global float2* veloctybffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); const float scale = 0.2f; f(d.x > 0 && d.x < grdresolton - 1 && d.y > 0 && d.y < grdresolton - 1){ float vl = vortctybffer[d.x - 1 + d.y * grdresolton]; float vr = vortctybffer[d.x + 1 + d.y * grdresolton]; float vb = vortctybffer[d.x + (d.y - 1) * grdresolton]; float vt = vortctybffer[d.x + (d.y + 1) * grdresolton]; float4 gradv = (float4)(vr - vl vt - vb 0.0f 0.0f); float4 z = (float4)(0.0f 0.0f 1.0f 0.0f); } } f(dot(gradv gradv)){ float4 vortctyforce = scale * cross(gradv z); veloctybffer[d.x + d.y * grdresolton] += vortctyforce.xy * dt; }
kernel vod addforce(const float x const float y const float2 force const nt grdresolton global float2* veloctybffer const float4 densty global float4* denstybffer) { nt2 d = (nt2)(get_global_d(0) get_global_d(1)); float dx = ((float)d.x / (float)grdresolton) - x; float dy = ((float)d.y / (float)grdresolton) - y; } float rads = 0.001f; float c = ex( - (dx * dx + dy * dy) / rads ) * dt; veloctybffer[d.x + d.y * grdresolton] += c * force; denstybffer[d.x + d.y * grdresolton] += c * densty;
Felhatóerő és gravtácó f boy ( d ( T T0 )) ˆ Termodnamka szmlácó (felhők) 3 dmenzóban Más rács tísok: a vektormezőkre FCC Tömör testekkel való nterakcó (voxelzálás határfeltételek kezelése)
Céla az átárás megteremtése OenGL és DrectX támogatás Megoszthatóak Általános bffer obektmok (l. vertex bffer) Textúrák Render bfferek A megosztandó obektmokat a grafks API hozza létre OenCL-bel használat előtt zároln kell Az obektm használata kzárólagos!
OenGL és OenCL kontexts megosztás GL_SHARING_EXTENSION OenGL kontexts nformácók cl_nt clgetglcontextinfokhr(const cl_context_roertes *ros cl_gl_context_nfo aram_name sze_t aram_vale_sze vod* aram_vale sze_t* aram_vale_sze_ret) CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR CL_DEVICES_FOR_GL_CONTEXT_KHR
OenGL és OenCL kontexts megosztás OenCL kontexts létrehozás cl_context clcreatecontext(const cl_context_roertes *ros cl_nt nm_devces const cl_devce_d *devces vod (*fn_notfy)(...) vod *ser_data cl_nt *errcode_ret) Tladonságok: CL_GL_CONTEXT_KHR: OenGL kontexts CL_WGL_HDC_KHR: az OenGL kontexts HDC-e CL_CONTEXT_PLATFORM: latform_d
Kontexts megosztása IntGL(); cl_latform latform = createplatform(); cl_devce_d devce_d = createdevce(latform CL_DEVICE_TYPE_GPU); cl_context sharedcontext = 0; f(checksharngsort(devce_d)){ cl_context_roertes ros[] = { CL_GL_CONTEXT_KHR (cl_context_roertes)wglgetcrrentcontext() CL_WGL_HDC_KHR (cl_context_roertes)wglgetcrrentdc() CL_CONTEXT_PLATFORM (cl_context_roertes)latform 0 }; } sharedcontext = clcreatecontext(ros 1 &devce_d NULL NULL &err);
Bffer obektmok megosztása cl_mem clcreatefromglbffer(cl_context context cl_mem_flags flags GLnt bfob cl_nt* errcode_ret) Image obektmok megosztása cl_mem clcreatefromgltextre2d(cl_context context cl_mem_flags flags GLenm textre_target GLnt mlevel GLnt textre cl_nt* errcode_ret)
Render bffer megosztása cl_mem clcreatefromglrenderbffer(cl_context context cl_mem_flags flags GLnt renderbffer cl_nt* errcode_ret) Az OenCL obektmok tladonsága Létrehozáskor aktáls értékek alaán Nem követk az OenGL obektm változásat! Amennyben változk úra meg kell osztan!
Bffer obektm megosztása OenGL vertex bffer mnt OenCL memóra obektm GLnt vbo; glgenbffers(1 &vbo); glbndbffer(gl_array_buffer vbo); glbfferdata(gl_array_buffer sze 0 GL_DYNAMIC_DRAW); cl_mem vbocl; vbocl = clcreatefromglbffer(sharedcontext CL_MEM_WRITE_ONLY vbo NULL);
Obektm lefoglalása cl_nt clenqeeacqreglobects(cl_command_qee command cl_nt nm_obects const cl_mem* mem_obects...) Obektm felszabadítása cl_mem clenqeereleaseglobects(cl_command_qee command cl_nt nm_obects const cl_mem* mem_obects...) Mnden használat előtt le kell foglaln Használat tán fel kell szabadítan
Sznkronzácó OenGL és OenCL között Nncs exlct sznkronzácó! Szüksége lenne mndkét API támogatására Mndkét API oldalán a csővezeték kürítése OenGL: glfnsh() OenCL: clfnsh() Imlementácó függően más megoldás s lehet glflsh() és clenqeebarrer()
Bffer obektm használata OenGL vertex bffer mnt OenCL memóra obektm // OenGL hívások glfnsh(); clenqeeacqreglobects(command 1 &vbocl 0 NULL NULL); // Kernel araméterek beállítása és kernel végrehatás clfnsh(); clenqeereleaseglobects(commands 1 &vbocl 0 NULL NULL); // OenGL hívások