This commit is contained in:
2026-05-04 08:57:06 -04:00
parent fdfd239962
commit f07c1190ee
18 changed files with 250 additions and 42 deletions

View File

@ -6,32 +6,33 @@ avariable = bla
anothervar = 1.2,1.3, 1.5 //this is a comment anothervar = 1.2,1.3, 1.5 //this is a comment
operatingmode = 1 operatingmode = 3
//1 - STL output //1 - STL output
//2 - count triangles //2 - count triangles
//3 - count area //3 - count area
verbosity = 0 verbosity = 2
//domain //domain
xyz_min = -1.2,-1.2,-1.2 xyz_min = -2.0,-2.0,-2.0
xyz_max = 1.2,1.2,1.2 xyz_max = 2.0,2.0,2.0
Nx = 32 Nx = 128
Ny = 32 Ny = 128
Nz = 32 Nz = 128
//execution parallelism pars //execution parallelism pars
nblockdiv = 32 nblockdiv = 64
nthreads = 256 nthreads = 256
//function specific parameters //function specific parameters
//not all pars apply to all functions //not all pars apply to all functions
isjulia = 0 isjulia = 1
juliac = 0.0,0.0,0.0 juliac = 0.0,0.0,0.0
exponent = 8.0 exponent = 4.0
fractaliter = 64 fractaliter = 100
threshhold = 2.0
freezethresh = 10.0 freezethresh = 10.0
threshold = 0.2
scale = 0.5

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -33,8 +33,11 @@ namespace fractallevelset
int verbosity; int verbosity;
__host__ __device__ inputpars(); __host__ __device__ inputpars();
void __host__ print();
}; };
int parse_input(const char *fname, inputpars *pars); int parse_input(const char *fname, inputpars *pars);
void inputmain(int argc, char *argv[]); void inputmain(int argc, char *argv[]);

View File

@ -38,8 +38,8 @@ class cuvec4f;
// #define AMSCU_CONST // #define AMSCU_CONST
// #endif // #endif
#define AMSCLS_MANDELBROT //#define AMSCLS_MANDELBROT
//#define AMSCLS_PPKFRACTAL #define AMSCLS_PPKFRACTAL
namespace amscuda namespace amscuda
@ -156,6 +156,13 @@ struct marchingtet_pars
__device__ __host__ marchingtet_pars(); __device__ __host__ marchingtet_pars();
}; };
void marchingtets_gpu(marchingtet_pars mtpars, bagoftriangles *mesh, int nblockdiv=32, int nthreads=256, int verbose=0);
int64_t marchingtets_tricount_gpu(marchingtet_pars mtpars, int nblockdiv=32, int nthreads=256, int verbose=0);
float marchingtets_area_gpu(marchingtet_pars mtpars, int nblockdiv=32, int nthreads=256, int verbose=0);
}; //end namespaces }; //end namespaces
}; };

View File

@ -20,10 +20,14 @@ __host__ __device__ float main_function(cuvec3f pos, main_functionpars &pars)
{ {
float ret = 0.0f; float ret = 0.0f;
float wr,wtheta,wphi; float wr,wtheta,wphi;
cuvec3f w; cuvec3f w,c;
int I; int I;
w = pos; w = pos;
if(pars.isjulia)
c = pars.juliac;
else
c = pos;
for(I=0;I<pars.fractaliter;I++) for(I=0;I<pars.fractaliter;I++)
{ {
@ -31,11 +35,11 @@ __host__ __device__ float main_function(cuvec3f pos, main_functionpars &pars)
wtheta = ::acos(w.y/wr); wtheta = ::acos(w.y/wr);
wphi = ::atan2(w.x,w.z); wphi = ::atan2(w.x,w.z);
if(wr>pars.freezethresh) break; if(wr>pars.freezethresh) break;
wr = ::pow(wr,8.0f); wr = ::pow(wr,pars.exponent);
wtheta = wtheta*8.0f; wtheta = wtheta*pars.exponent;
wphi = wphi*8.0f; wphi = wphi*pars.exponent;
w = cuvec3f(wr*sin(wtheta)*sin(wphi),wr*cos(wtheta),wr*sin(wtheta)*cos(wphi)); w = cuvec3f(wr*sin(wtheta)*sin(wphi),wr*cos(wtheta),wr*sin(wtheta)*cos(wphi));
w = w + pos; w = w + c;
} }
ret = cuvec3f_norm(w)-pars.threshold; ret = cuvec3f_norm(w)-pars.threshold;
@ -44,22 +48,89 @@ __host__ __device__ float main_function(cuvec3f pos, main_functionpars &pars)
}; };
#endif #endif
#ifdef AMSCLS_JULIA
__host__ __device__ float main_function(cuvec3f pos, main_functionpars &pars)
{
float ret = 0.0f;
return ret;
};
#endif
#ifdef AMSCLS_PPKFRACTAL #ifdef AMSCLS_PPKFRACTAL
__host__ __device__ float main_function(cuvec3f pos, main_functionpars &pars) __host__ __device__ float main_function(cuvec3f pos, main_functionpars &pars)
{ {
float ret = 0.0f; float ret = 1E6;
cuvec3f z;
float offset;
cuvec3f c;
float dr = 1.0f;
float signfactor;
int I;
if(pars.isjulia)
{
c = pars.juliac;
offset = 0.0;
}
else
{
c = pos;
offset = 1.0;
}
signfactor = (pars.scale<0.0f)? 0.95f : 1.0f;
z = pos;
for(I=0;I<pars.fractaliter;I++)
{
if(::fabs(z.y)>8.0f)
{
break;
}
float sx,cx,sz,cz,shy,chy;
sx = sinf(z.x);
cx = cosf(z.x);
sz = sinf(z.z);
cz = cosf(z.z);
shy = sinhf(z.y);
chy = coshf(z.y);
z = cuvec3f(sx*chy,cx*cz*shy,sz*chy)*pars.scale + c;
float stretch = 0.75f*::sqrtf(chy*chy + shy*shy);
if(stretch>0.9f) stretch = 0.9f;
dr = ::fabs(pars.scale)*signfactor*stretch*dr + offset;
float q = 1.0f/dr;
if(q<ret) ret = q;
}
return ret; return ret;
}; };
/*
float DE(vec3 pos) {
vec3 z = pos;
vec3 juliaC = Julia ? JuliaC : pos;
float offset = Julia ? 0.0 : 1.0;
float dr = 1.0;
// negative scale swaps sign each iteration, which affects the dr growth
float signFactor = Scale < 0.0 ? 0.95 : 1.0;
float de = 1e20;
for (int i = 0; i < Iterations; i++) {
// just for stability, not a real escape condition
if (abs(z.y) > 8.) break;
float sx = sin(z.x), cx = cos(z.x);
float sz = sin(z.z), cz = cos(z.z);
// shy and chy can be replaced with taylor approximations to save cycles
float shy = sinh(z.y), chy = cosh(z.y);
z = vec3(sx * chy, cx * cz * shy, sz * chy) * Scale + juliaC;
// 0.75 and 0.9 are magic constants
float stretch = 0.75 * sqrt(chy * chy + shy * shy);
stretch = max(0.9, stretch);
dr = abs(Scale) * signFactor * stretch * dr + offset;
de = min(de, 1.0 / dr);
}
return DEMultiplier* de;
}
*/
#endif #endif
};//end namespace fractallevelset };//end namespace fractallevelset

View File

@ -104,6 +104,31 @@ namespace fractallevelset
} }
} }
__global__ void marchingtets_gpu_debug2(marchingtet_pars mtpars, float *outbuffer)
{
int64_t psize = (int64_t)mtpars.Nx*(int64_t)mtpars.Ny*(int64_t)mtpars.Nz;
int64_t nt = blockDim.x*gridDim.x;
int64_t tn = threadIdx.x + blockIdx.x*blockDim.x;
int64_t I;
int Ix,Iy,Iz;
mtcube cube;
for(I=tn;I<psize;I+=nt)
{
Ix = I%(mtpars.Nx);
Iy = (I/(mtpars.Nx))%mtpars.Ny;
Iz = (I/(mtpars.Nx*mtpars.Ny))%mtpars.Nz;
if(Iz==(mtpars.Nz/2))
{
mtgetcube(mtpars,I,cube);
cube.eval_function(mtpars.pars);
outbuffer[Ix + Iy*mtpars.Nx] = cube.fevals[8];
}
}
}
__global__ void marchingtets_gpu_areacount(marchingtet_pars mtpars, float *areabuffer) __global__ void marchingtets_gpu_areacount(marchingtet_pars mtpars, float *areabuffer)
{ {
@ -173,21 +198,20 @@ namespace fractallevelset
return; return;
} }
void marchingtets_gpu(marchingtet_pars mtpars, bagoftriangles *mesh) void marchingtets_gpu(marchingtet_pars mtpars, bagoftriangles *mesh, int nblockdiv, int nthreads, int verbose)
{ {
//marchingtet_pars *dmtpars = NULL; //marchingtet_pars *dmtpars = NULL;
int *dtricountbuffer = NULL; int *dtricountbuffer = NULL;
float *dvertexbuffer = NULL; float *dvertexbuffer = NULL;
int64_t *hoffsetbuffer = NULL; int64_t *hoffsetbuffer = NULL;
int64_t *doffsetbuffer = NULL; int64_t *doffsetbuffer = NULL;
int nblocks,nthreads; int nblocks;
int64_t psize = (int64_t)mtpars.Nx*(int64_t)mtpars.Ny*(int64_t)mtpars.Nz; int64_t psize = (int64_t)mtpars.Nx*(int64_t)mtpars.Ny*(int64_t)mtpars.Nz;
int *htricountbuffer = NULL; int *htricountbuffer = NULL;
int64_t tricount; int64_t tricount;
nthreads = 256; nblocks = (int)(((psize/(int64_t)nthreads)+1L)/(int64_t)nblockdiv+1L);
nblocks = (int)(((psize/(int64_t)nthreads)+1L)/16L+1L);
cudaMalloc(&dtricountbuffer, nblocks*nthreads*sizeof(int)); cudaMalloc(&dtricountbuffer, nblocks*nthreads*sizeof(int));
htricountbuffer = new(std::nothrow) int[nblocks*nthreads]; htricountbuffer = new(std::nothrow) int[nblocks*nthreads];
@ -211,6 +235,7 @@ namespace fractallevelset
// cudaMalloc(&dmtpars,sizeof(marchingtet_pars)); // cudaMalloc(&dmtpars,sizeof(marchingtet_pars));
// cudaMemcpy(dmtpars,&mtpars,sizeof(marchingtet_pars),cudaMemcpyHostToDevice); // cudaMemcpy(dmtpars,&mtpars,sizeof(marchingtet_pars),cudaMemcpyHostToDevice);
if(verbose>=2)
printf("debug: launching marchingtets_gpu_tricount with <%d,%d>\n",nblocks,nthreads); printf("debug: launching marchingtets_gpu_tricount with <%d,%d>\n",nblocks,nthreads);
cudaError_t err = cudaSuccess; cudaError_t err = cudaSuccess;
marchingtets_gpu_tricount<<<nblocks,nthreads>>>(mtpars,dtricountbuffer); marchingtets_gpu_tricount<<<nblocks,nthreads>>>(mtpars,dtricountbuffer);
@ -226,6 +251,7 @@ namespace fractallevelset
tricount = mt_count_tris_and_accum_offset(htricountbuffer,dtricountbuffer,hoffsetbuffer,doffsetbuffer,nblocks,nthreads); tricount = mt_count_tris_and_accum_offset(htricountbuffer,dtricountbuffer,hoffsetbuffer,doffsetbuffer,nblocks,nthreads);
if(verbose>=1)
printf("marchingtets_gpu: triangle count = %ld\n",(long)tricount); printf("marchingtets_gpu: triangle count = %ld\n",(long)tricount);
mesh->vertices.resize(tricount*9); mesh->vertices.resize(tricount*9);
@ -257,6 +283,67 @@ namespace fractallevelset
return; return;
} }
int64_t marchingtets_tricount_gpu(marchingtet_pars mtpars, int nblockdiv, int nthreads, int verbose)
{
//marchingtet_pars *dmtpars = NULL;
int *dtricountbuffer = NULL;
int64_t *hoffsetbuffer = NULL;
int64_t *doffsetbuffer = NULL;
float *dvertexbuffer = NULL;
int nblocks;
int64_t psize = (int64_t)mtpars.Nx*(int64_t)mtpars.Ny*(int64_t)mtpars.Nz;
int *htricountbuffer = NULL;
int64_t tricount = 0;
nblocks = (int)(((psize/(int64_t)nthreads)+1L)/(int64_t)nblockdiv+1L);
cudaMalloc(&dtricountbuffer, nblocks*nthreads*sizeof(int));
htricountbuffer = new(std::nothrow) int[nblocks*nthreads];
cudaMalloc(&doffsetbuffer, nblocks*nthreads*sizeof(int64_t));
hoffsetbuffer = new(std::nothrow) int64_t[nblocks*nthreads];
//DEBUG
// float *debugbuffer = NULL;
// float *ddebugbuffer = NULL;
// debugbuffer = new(std::nothrow) float[nblocks*nthreads*25];
// cudaMalloc(&ddebugbuffer,sizeof(float)*nblocks*nthreads*25);
if(dtricountbuffer==NULL || htricountbuffer==NULL)
{
printf("marchingtets_gpu error: failed to allocate counting buffers\n");
marchingtets_gpu_cleanup(&dtricountbuffer,&htricountbuffer,&dvertexbuffer,&doffsetbuffer,&hoffsetbuffer);
return 0;
}
// cudaMalloc(&dmtpars,sizeof(marchingtet_pars));
// cudaMemcpy(dmtpars,&mtpars,sizeof(marchingtet_pars),cudaMemcpyHostToDevice);
//printf("debug: launching marchingtets_gpu_tricount with <%d,%d>\n",nblocks,nthreads);
cudaError_t err = cudaSuccess;
marchingtets_gpu_tricount<<<nblocks,nthreads>>>(mtpars,dtricountbuffer);
cudaDeviceSynchronize();
err = cudaGetLastError();
if(err!=cudaSuccess)
{
printf("marchingtets_gpu_tricount error: %s\n",cudaGetErrorString(err));
}
//mt_debug1(debugbuffer,ddebugbuffer,nblocks,nthreads);
tricount = mt_count_tris_and_accum_offset(htricountbuffer,dtricountbuffer,hoffsetbuffer,doffsetbuffer,nblocks,nthreads);
if(verbose>=1)
printf("marchingtets_gpu_tricount: triangle count = %ld\n",(long)tricount);
marchingtets_gpu_cleanup(&dtricountbuffer,&htricountbuffer,&dvertexbuffer,&doffsetbuffer,&hoffsetbuffer);
return tricount;
}
void marchingtets_area_gpu_cleanup( void marchingtets_area_gpu_cleanup(
float **hareabuffer, float **hareabuffer,
float **dareabuffer float **dareabuffer
@ -266,18 +353,17 @@ namespace fractallevelset
if(*hareabuffer!=NULL) {delete[] *hareabuffer; *hareabuffer=NULL;} if(*hareabuffer!=NULL) {delete[] *hareabuffer; *hareabuffer=NULL;}
} }
float marchingtets_area_gpu(marchingtet_pars mtpars) float marchingtets_area_gpu(marchingtet_pars mtpars, int nblockdiv, int nthreads, int verbose)
{ {
//marchingtet_pars *dmtpars = NULL; //marchingtet_pars *dmtpars = NULL;
int nblocks,nthreads; int nblocks;
float *hareabuffer = NULL; float *hareabuffer = NULL;
float *dareabuffer = NULL; float *dareabuffer = NULL;
int I; int I;
float areasum = 0.0f; float areasum = 0.0f;
int64_t psize = (int64_t)mtpars.Nx*(int64_t)mtpars.Ny*(int64_t)mtpars.Nz; int64_t psize = (int64_t)mtpars.Nx*(int64_t)mtpars.Ny*(int64_t)mtpars.Nz;
nthreads = 256; nblocks = (int)(((psize/(int64_t)nthreads)+1L)/(int64_t)nblockdiv+1L);
nblocks = (int)(((psize/(int64_t)nthreads)+1L)/16L+1L);
cudaMalloc(&dareabuffer, nblocks*nthreads*sizeof(float)); cudaMalloc(&dareabuffer, nblocks*nthreads*sizeof(float));
hareabuffer = new(std::nothrow) float[nblocks*nthreads]; hareabuffer = new(std::nothrow) float[nblocks*nthreads];

View File

@ -96,6 +96,10 @@ namespace fractallevelset
amsarray<amsstring> alphanums; amsarray<amsstring> alphanums;
alphanums = s.splitalphanum(); alphanums = s.splitalphanum();
// printf("debug: alphanum[0]='%s'\n",alphanums[0].cstring);
// printf("debug: alphanum[1]='%s'\n",alphanums[1].cstring);
// printf("debug: alphanum[2]='%s'\n",alphanums[2].cstring);
for(I=0;I<alphanums.length&&I<3;I++) for(I=0;I<alphanums.length&&I<3;I++)
{ {
ret[I] = (float)(alphanums[I].strtonum()); ret[I] = (float)(alphanums[I].strtonum());
@ -124,6 +128,8 @@ namespace fractallevelset
{ {
if(varname==stringpars->at(I)[0]) if(varname==stringpars->at(I)[0])
{ {
// printf("debug: par[0]='%s'\n",stringpars->at(I)[0].cstring);
// printf("debug: par[1]='%s'\n",stringpars->at(I)[1].cstring);
*val = (float) stringpars->at(I)[1].strtonum(); *val = (float) stringpars->at(I)[1].strtonum();
} }
} }
@ -193,6 +199,7 @@ namespace fractallevelset
inputpars pars; inputpars pars;
marchingtet_pars mtpars; marchingtet_pars mtpars;
main_functionpars mfpars; main_functionpars mfpars;
bagoftriangles mesh;
if(argc<3) if(argc<3)
{ {
@ -241,22 +248,55 @@ namespace fractallevelset
mtpars.pars = mfpars; mtpars.pars = mfpars;
//execute model based on operatingmode //execute model based on operatingmode
if(pars.verbosity>=1)
pars.print();
if(pars.operatingmode==omode_stloutput) if(pars.operatingmode==omode_stloutput)
{ {
marchingtets_gpu(mtpars,&mesh,pars.nblockdiv,pars.nthreads,pars.verbosity);
mesh.save_stl(fnameout.cstring);
} }
else if(pars.operatingmode==omode_counttriangles) else if(pars.operatingmode==omode_counttriangles)
{ {
int64_t tricount = 0;
tricount = marchingtets_tricount_gpu(mtpars,pars.nblockdiv,pars.nthreads,pars.verbosity);
printf("triangle count = %ld\n",(long)tricount);
} }
else if(pars.operatingmode==omode_countarea) else if(pars.operatingmode==omode_countarea)
{ {
float area = 0.0f;
area = marchingtets_area_gpu(mtpars,pars.nblockdiv,pars.nthreads,pars.verbosity);
printf("area = %1.5g\n",area);
} }
} }
__host__ void inputpars::print()
{
printf("inputpars:\n");
{
printf("\t operatingmode = %d \n",operatingmode);
printf("\t verbosity = %d\n",verbosity);
printf("\t xyz_min = (%1.3g,%1.3g,%1.3g)\n",xyz_min[0],xyz_min[1],xyz_min[2]);
printf("\t xyz_max = (%1.3g,%1.3g,%1.3g)\n",xyz_max[0],xyz_max[1],xyz_max[2]);
printf("\t Nx = %d\n",Nx);
printf("\t Ny = %d\n",Ny);
printf("\t Nz = %d\n",Nz);
printf("\t nblockdiv = %d\n",nblockdiv);
printf("\t nthreads = %d\n",nthreads);
printf("\t isjulia = %d\n",(int)isjulia);
printf("\t juliac = (%1.3g,%1.3g,%1.3g)\n",juliac[0],juliac[1],juliac[2]);
printf("\t exponent = %1.3f\n",exponent);
printf("\t fractaliter = %d\n",fractaliter);
printf("\t threshold = %1.3f\n",threshold);
printf("\t freezethresh = %1.3f\n",freezethresh);
printf("\t scale = %1.3f\n",scale);
}
}
};//end namespace fractallevelset };//end namespace fractallevelset