oblique_mc

Monte Carlo in Single Layer Biological Tissue
git clone anongit@rnpnr.xyz:oblique_mc.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 3a89a23738d3e253f9d93c2943f8748a479861e9
Parent: 4e8459bb31f45737d053b973d2a786d15033faef
Author: Randy Palamar
Date:   Tue, 26 Mar 2024 22:15:16 -0600

rewrite in c

Diffstat:
DPhoton.cpp | 223-------------------------------------------------------------------------------
DPhoton.h | 34----------------------------------
Mbuild.sh | 5+++--
Dmain.cpp | 133-------------------------------------------------------------------------------
Amcml.c | 470+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dutils.cpp | 54------------------------------------------------------
Dutils.h | 60------------------------------------------------------------
7 files changed, 473 insertions(+), 506 deletions(-)

diff --git a/Photon.cpp b/Photon.cpp @@ -1,223 +0,0 @@ -// Photon.cpp: implementation of the Photon class. -// -////////////////////////////////////////////////////////////////////// - -#include "Photon.h" -#include "utils.h" - -#include <math.h> -///////////////////////////////////////// - - -double Photon::Rsp=0.0; -///////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -Photon::Photon() -{ - w=1.0; - nScatter=0; - dead=false; - posx=0.0; - posy=0.0; - posz=0.0; -////////incident direction - ux=sin(th_in)*n0/n; - uy=0.0; - uz=sqrt(1-ux*ux); -////////////////////////////////////// - s=0.0; - db=0.0; -} - -Photon::~Photon() -{ - -} - -void Photon::Launch() -{ - double rsp, sinthi, sintht, costhi, costht, raux1, raux2; - sinthi=sin(th_in); - costhi=cos(th_in); - sintht=ux; - costht=uz; - raux1=sinthi*costht-costhi*sintht; - raux1=raux1*raux1; - raux2=sinthi*costht+costhi*sintht; - raux2=raux2*raux2; - rsp=0.5*(raux1/raux2+raux1*(1-raux2)/raux2/(1-raux1)); - Rsp+=w*rsp; - w=w*(1-rsp); -} - -void Photon::CalStep() -{ - if (s < ZERO) { - double ran = random_uniform(); - s = -log(ran + EPS); - } -} - -void Photon::Caldb() -{ - if (uz<-ZERO) //travel up to reach upper layer - { - db=-posz/uz; - } - else if (uz>ZERO) //travel down to reach bottom layer - { - db=(d-posz)/uz; - } - else - { - db=BIGVAL; // A big value - } -} - -bool Photon::HitBoundary() -{ - if(db*mut<=s) - return true; - else - return false; -} - -void Photon::Move(double ds) //ds has dimension in cm -{ - posx+=ds*ux; - posy+=ds*uy; - posz+=ds*uz; - s=s-ds*mut; -} - -void Photon::Absorb() // calculate absorption -{ - double dw; - dw=w*mua/mut;//3.24 - w-=dw; - if (w<0) - { - dead=true; - w=0.0; - dw=w+dw; //dw equals the small weight dw=(w-dw)+dw - } -} - -void Photon::Scatter() // calculate next propagation direction -{ - if (dead) - return; - - double costheta, fei, ran; - ran = random_uniform(); - if (g != 0) { - double aa = (1 - g * g) / (1 - g + 2 * g * ran); - costheta = (1 + g * g - aa * aa) / (2 * g); - if (costheta < -1) - costheta = -1; - else if (costheta > 1) - costheta = 1; - } else { - costheta = 2 * ran - 1; - } // (3.28) - - double sintheta, sinfei, cosfei; - sintheta = sqrt(1 - costheta * costheta); - ran = random_uniform(); - fei = 2 * PI * ran; // (3.29) - cosfei = cos(fei); - if (fei < PI) { - sinfei = sqrt(1 - cosfei * cosfei); - } else { - sinfei = -sqrt(1 - cosfei * cosfei); - } - - double uux, uuy, uuz; - if ((SIGN(uz) * uz) <= (1 - ZERO)) { - uux = sintheta * (ux * uz * cosfei - uy * sinfei) - / sqrt(1 - uz * uz) + ux * costheta; - uuy = sintheta * (uy * uz * cosfei + ux * sinfei) - / sqrt(1 - uz * uz) + uy * costheta; - uuz = -sintheta * cosfei * sqrt(1 - uz * uz) + uz * costheta; - // (3.24) - } else { - // close to normal propagation - uux = sintheta * cosfei; - uuy = sintheta * sinfei; - uuz = SIGN(uz) * costheta; - } // (3.30) - ux = uux; - uy = uuy; - uz = uuz; - nScatter++; -} - -void Photon::ReflectTransmit() // deal with photon across boundary -{ - double sinalphai,sinalphat,ralphai; - sinalphai=sqrt(1-(uz)*(uz)); - sinalphat=sinalphai*n/n0; //3.35 - if (sinalphat<ZERO) // close to normal - { - ralphai=(n-n0)/(n+n0); - ralphai=ralphai*ralphai; - } - else if (sinalphat>1)// Total reflection - { - ralphai=1; - } - else - { - double A,B; - A=sinalphai*sqrt(1-sinalphat*sinalphat)-sinalphat*sqrt(1-sinalphai*sinalphai); - A=A*A; - B=sinalphai*sqrt(1-sinalphat*sinalphat)+sinalphat*sqrt(1-sinalphai*sinalphai); - B=B*B; - ralphai=0.5*(2*A-A*A-A*B)/(B*(1-A));//(3.36) - } - double ran = random_uniform(); - if (ran<=ralphai) //rebound to current layer - { - uz=-uz; - } - else //cross the boundary - { - if (uz<-ZERO) //hit upper doundary - { - if(posx>-x_offset&&posx<x_offset&&posy>-y_offset&&posy<y_offset) - { - u32 xoff = (posx + x_offset) / dx * Rd_xy.Ny; - u32 yoff = (posy + y_offset) / dy; - Rd_xy.b[xoff + yoff] += w; - } - dead=true; - } - else //hit bottom boundary - { - dead=true; - } - } -} - -void Photon::Termination() //Russian roulette survial test -{ - if (dead) - return; - - if (w > 1e-4) - return; - - double m = 10; - double e = random_uniform(); - if (m * e > 1) { - w = 0; - dead = true; - } else { - w *= m; - } -} diff --git a/Photon.h b/Photon.h @@ -1,34 +0,0 @@ -// Photon.h: interface for the Photon class. -// describe the behaviors of photons in Tissue -////////////////////////////////////////////////////////////////////// - -#ifndef _PHOTON_H -#define _PHOTON_H - -class Photon -{ -public: - double posx, posy, posz; // current position of photon - double ux, uy, uz; // current direction of photon - int nScatter; // # of scattering events experienced - double w; // weight - double s; // s is the remaining dimensionless step-size - double db; // the distance from boundary - bool dead; // True if photon is dead, otherwise False - - static double Rsp; // specular reflectance - - Photon(); - virtual ~Photon(); - void Launch(); // calculate specular reflectance at the surface - void CalStep(); // calculate dimensionless step length - void Caldb(); // calculate the travel length to reach the boundary - bool HitBoundary(); // True if hitboudary - void Move(double ds); // move photon towards boundary - void Absorb(); // calculate absorption - void Scatter(); // calculate next propagation direction - void ReflectTransmit(); // deal with photon across boundary - void Termination(); // Russian roulette survial test -}; - -#endif // _PHOTON_H diff --git a/build.sh b/build.sh @@ -1,5 +1,6 @@ #!/bin/sh +set -x -srcs="main.cpp Photon.cpp utils.cpp" +srcs="mcml.c" -c++ -O3 -Wall -march=native $srcs -o mcml +clang -O3 -Wall -march=native $srcs -o mcml diff --git a/main.cpp b/main.cpp @@ -1,133 +0,0 @@ - /* Hybrid-MC by Li Li, Last modified 03/07 -refrence: Wang, "Biomedical optics", chpater3&6 */ - - -/* Programming notes -1. Use Cartesian coordinates. -2. Incident beam in x-z plane. -*/ - -#include <iostream> -#include <fstream> -#include <string> - -#define GLOBALORIGIN -#include "utils.h" -#undef GLOABLORIGIN - -#include "Photon.h" - - -using namespace std; -//////////////////////////////////////////////// -int main(void) -{ -////////Input Interface//////////////////// - cout<<"*****************************************"<<endl; - cout<<"Hybrid Monte Carlo for Homogeneous Slab with Oblique incidence"<<endl; - cout<<"By Li Li, 04/2007"<<endl; - cout<<"Refrence: Wang, Biomedical optics, chpater3&6"<<endl; - cout<<"*****************************************"<<endl; - cout<<endl; - - random_init(); - - cout<<"File name(Input:*.mci; Output:*.mco): "; - string sFilename, sInfilename, sOutfilename; - cin>>sFilename; - sInfilename=sFilename+".mci"; - sOutfilename=sFilename+".mco"; - ifstream Infile; - Infile.open(sInfilename.c_str()); - if(Infile.fail()) - { - cerr<<"Error! Can't open input file. Err Code 1"<<endl; - exit(1); - } - // double P0, R; //Incident energy/power P0, Beam diameter R - // Infile>>P0>>R; - int nNum_photons; //# of photons used - Infile>>nNum_photons; - Infile>>th_in; - th_in=th_in/180*PI; - Infile>>dx>>dy>>Nx>>Ny; - x_offset=dx*Nx/2; - y_offset=dy*Ny/2; - Infile>>n>>mua>>mus>>g>>d; - mut=mua+mus; - Infile.close(); -///////////////////////////////////////////// - -////////for timing/////////////////////////// - time_t start,end; //simulation beginning and finishing time - time(&start); -///////////////////////////////////////////// - int tmp1; - - alloc_mat(&Rd_xy, Nx, Ny); - -//////////Propagate photons//////////////////////////////// - for (tmp1=1;tmp1<=nNum_photons;tmp1++) - { - Photon photon; - photon.Launch(); - do - { - photon.CalStep(); - photon.Caldb(); - if(photon.HitBoundary()) - { - photon.Move(photon.db); - photon.ReflectTransmit(); - } - else - { - photon.Move(photon.s/mut); - photon.Absorb(); - photon.Scatter(); - } - photon.Termination(); - } while(!photon.dead); - if (tmp1%(nNum_photons/10)==0) - { - cout<<tmp1<<" photons are done!"<<endl; - } - } - - time(&end); - int CompuTime; - CompuTime=end-start; - cout<<"This simulation take "<<CompuTime<<" seconds!"<<endl; -///////////////////////////////////////////// - - -////////Write data before convolution//////// - ofstream f_out(sOutfilename.c_str()); - f_out<<"/////////////Grid coordinates///////////"<<endl; - f_out<<"x (cm): "; - for (tmp1=0;tmp1<Nx;tmp1++) - { - f_out<<(tmp1+0.5)*dx-x_offset<<' '; - } - f_out<<endl; - f_out<<"y (cm): "; - for (tmp1=0;tmp1<Ny;tmp1++) - { - f_out<<(tmp1+0.5)*dy-y_offset<<' '; - } - f_out<<endl; - f_out<<"/////////////////////////////////////////"<<endl; - - - f_out<<"///////////////Rd_xy/////////////////////"<<endl; - double scale=nNum_photons*dx*dy; - double *b = Rd_xy.b; - for (u32 i = 0; i < Rd_xy.Nx; i++) { - for (u32 j = 0; j < Rd_xy.Ny; j++) - f_out << b[j] / scale << ' '; - f_out << endl; - b += Rd_xy.Ny; - } - f_out<<endl; - f_out<<"/////////////////////////////////////////"<<endl; -} diff --git a/mcml.c b/mcml.c @@ -0,0 +1,470 @@ +/* Oblique Monte Carlo + * Written by Randy Palamar - March 2024 + * Based on: Hybrid-MC by Li Li + * Refrence: Wang, "Biomedical optics", chpater 3 & 6 + */ + +/* Details: + * - Uses Cartesian coordinates. + * - Beam is incident in x-z plane. + */ + +#include <math.h> +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +#define SGN(x) ((x) >= 0 ? 1 : -1) +#define ABS(x) ((x) >= 0 ? x : -x) + +#define IS_SPACE(x) ((x) == '\n' || (x) == '\r' || (x) == '\t' || (x) == ' ') + +#define ZERO 1.0e-6 +#define BIGVAL 1.0e6 +#define EPS 1.0e-9 + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint8_t u8; +typedef double f64; +typedef ptrdiff_t size; + +typedef struct { u8 *data; size len; } s8; + +typedef struct { + f64 x, y ,z; +} Vec3; + +typedef struct { + u32 Nx, Ny; + f64 *b; +} Mat2; + +typedef struct { + Vec3 pos; + Vec3 dir; + f64 w; + u32 n_scatters; + u32 dead; +} Photon; + +/* global data that will not be modified after startup */ +static struct { + f64 dx, dy; + f64 xoff, yoff; + u32 Nx, Ny; + u32 N_photons; + + f64 mu_a, mu_s, mu_t; + f64 g, d; + + f64 n, n0; + f64 theta_i; +} gctx; + +/* these will be modified; FIXME: multithreading */ +static Mat2 Rd_xy; +static u64 rand_state[2]; + +static void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(1); +} + +static s8 +read_file(const char *fname) +{ + int fd; + s8 ret; + + if ((fd = open(fname, O_RDONLY)) < 0) + die("open: %s\n", fname); + + ret.len = lseek(fd, 0L, SEEK_END); + ret.data = malloc(ret.len); + if (ret.data == NULL) + die("malloc\n"); + lseek(fd, 0L, SEEK_SET); + + size rlen; + do { + rlen = read(fd, ret.data, ret.len); + } while (rlen == -1 && errno == EINTR); + close(fd); + + if (rlen != ret.len) + die("read: %s\n", fname); + + return ret; +} + +static s8 +split_at_space(s8 s) +{ + s8 ret; + + /* skip leading white space */ + while (IS_SPACE(*s.data) && s.len) { + s.data++; + s.len--; + } + ret.data = s.data; + + while (!IS_SPACE(*s.data) && s.len) { + s.data++; + s.len--; + } + s.data[0] = 0; + ret.len = s.data - ret.data; + return ret; +} + +/* fills in global ctx based on input */ +static void +load_input(const char *name) +{ + s8 f = read_file(name); + s8 s = split_at_space(f); + + char *e; + #define ADVANCE_S(_s) do {\ + _s.data = (u8 *)e + 1;\ + _s.len = f.len - (f.data - s.data);\ + _s = split_at_space(_s);\ + } while (0); + + errno = 0; + gctx.N_photons = (u64)strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.theta_i = strtod((char *)s.data, &e) * M_PI / 180; + ADVANCE_S(s); + gctx.dx = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.dy = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.Nx = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.Ny = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.n = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.mu_a = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.mu_s = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.g = strtod((char *)s.data, &e); + ADVANCE_S(s); + gctx.d = strtod((char *)s.data, &e); + + gctx.xoff = gctx.dx * gctx.Nx / 2; + gctx.yoff = gctx.dy * gctx.Ny / 2; + gctx.mu_t = gctx.mu_a + gctx.mu_s; + + gctx.n0 = 1.0; + + #undef ADVANCE_S + + if (errno != 0) + die("strtod: errno = %d\n", errno); + + free(f.data); +} + +static void +random_init(void) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + rand_state[0] = (intptr_t)&printf ^ ts.tv_sec + ^ ((u64)ts.tv_nsec * 0xAC5533CD); + rand_state[1] = (intptr_t)&malloc ^ ts.tv_sec + ^ ((u64)ts.tv_nsec * 0xAC5533CD); +} + +static u64 +xoroshiro128plus(u64 s[2]) +{ + u64 s0 = s[0]; + u64 s1 = s[1]; + u64 result = s0 + s1; + s1 ^= s0; + s[0] = ((s0 << 24) | (s0 >> 40)) ^ s1 ^ (s1 << 16); + s[1] = (s1 << 37) | (s1 >> 27); + return result; +} + +static f64 +random_uniform(void) +{ + return xoroshiro128plus(rand_state) / (f64)UINT64_MAX; +} + +static void +alloc_mat2(Mat2 *m, u32 x, u32 y) +{ + m->b = calloc(x * y, sizeof(f64)); + if (m->b == NULL) + die("calloc\n"); + m->Nx = x; + m->Ny = y; +} + +static void +launch_photon(Photon *p) +{ + p->pos = (Vec3){0, 0, 0}; + p->dir.x = sin(gctx.theta_i) * gctx.n0 / gctx.n; + p->dir.y = 0; + p->dir.z = sqrt(1 - p->dir.x * p->dir.x); + p->n_scatters = 0; + p->dead = 0; + + f64 sin_ti = sin(gctx.theta_i); + f64 cos_ti = cos(gctx.theta_i); + f64 sin_tt = p->dir.x; + f64 cos_tt = p->dir.z; + f64 raux1 = sin_ti * cos_tt - cos_ti * sin_tt; + raux1 *= raux1; + f64 raux2 = sin_ti * cos_tt + cos_ti * sin_tt; + raux2 *= raux2; + f64 rsp = raux1 / raux2 + raux1 * (1 - raux2) / raux2 / (1 - raux1); + rsp *= 0.5; + p->w = (1.0 - rsp); +} + +static void +move_photon(Photon *p, f64 s) +{ + p->pos.x += s * p->dir.x; + p->pos.y += s * p->dir.y; + p->pos.z += s * p->dir.z; +} + +static void +absorb_photon(Photon *p) +{ + f64 dw = p->w * gctx.mu_a / gctx.mu_t; /* eq 3.24 */ + p->w -= dw; + if (p->w < 0) + p->dead = 1; +} + +static void +reflect_or_transmit_photon(Photon *p) +{ + f64 sin_ai = sqrt(1 - p->dir.z * p->dir.z); + f64 sin_at = sin_ai * gctx.n / gctx.n0; /* eq. 3.35 */ + + f64 r_ai; + if (sin_at < ZERO) { /* roughly normal */ + r_ai = (gctx.n - gctx.n0) / (gctx.n + gctx.n0); + r_ai *= r_ai; + } else if (sin_at > 1.0) { /* TIR */ + r_ai = 1; + } else { + f64 A = sin_ai * sqrt(1 - sin_at * sin_at) + - sin_at * sqrt(1 - sin_ai * sin_ai); + A *= A; + f64 B = sin_ai * sqrt(1 - sin_at * sin_at) + + sin_at * sqrt(1 - sin_ai * sin_ai); + B *= B; + r_ai = 0.5 * (2 * A - A * A - A * B) / (B * (1 - A)); /* eq 3.36 */ + } + + f64 r = random_uniform(); + if (r <= r_ai) { + /* rebound to current layer */ + p->dir.z = -p->dir.z; + } else { + /* cross the boundary */ + if (p->dir.z < -ZERO) { + /* hit upper boundary. record reflactance if + * we are in bounds of output region */ + if (p->pos.x > -gctx.xoff && p->pos.x < gctx.xoff && + p->pos.y > -gctx.yoff && p->pos.y < gctx.yoff) { + u32 ri = (p->pos.x + gctx.xoff) / gctx.dx; + u32 ci = (p->pos.y + gctx.yoff) / gctx.dy; + Rd_xy.b[ri * Rd_xy.Ny + ci] += p->w; + } + } + p->dead = 1; + } +} + +static void +scatter_photon(Photon *p) +{ + if (p->dead) + return; + + f64 cos_t, fei; + f64 g = gctx.g; + if (g != 0) { + f64 r = random_uniform(); + f64 aa = (1 - g * g) / (1 - g + 2 * g * r); + cos_t = (1 + g * g - aa * aa) / (2 * g); + if (cos_t < -1) + cos_t = -1; + else if (cos_t > 1) + cos_t = 1; + } else { + cos_t = 2 * random_uniform() - 1; + } /* eq. (3.28) */ + + f64 sin_t, sin_fei, cos_fei; + sin_t = sqrt(1 - cos_t * cos_t); + fei = 2 * M_PI * random_uniform(); /* eq. (3.29) */ + cos_fei = cos(fei); + sin_fei = sin(fei); + + f64 uux, uuy, uuz; + if (ABS(p->dir.z) <= (1 - ZERO)) { + /* eq. (3.24) */ + Vec3 u = p->dir; + uux = sin_t * (u.x * u.z * cos_fei - u.y * sin_fei) + / sqrt(1 - u.z * u.z) + u.x * cos_t; + uuy = sin_t * (u.y * u.z * cos_fei + u.x * sin_fei) + / sqrt(1 - u.z * u.z) + u.y * cos_t; + uuz = -sin_t * cos_fei * sqrt(1 - u.z * u.z) + u.z * cos_t; + } else { + /* close to normal propagation */ + /* eq. (3.30) */ + uux = sin_t * cos_fei; + uuy = sin_t * sin_fei; + uuz = SGN(p->dir.z) * cos_t; + } + p->dir.x = uux; + p->dir.y = uuy; + p->dir.z = uuz; + p->n_scatters++; + +} + +static void +check_photon_life(Photon *p) +{ + if (p->dead) + return; + + if (p->w > 1e-4) + return; + + f64 m = 10; + f64 e = random_uniform(); + if (m * e > 1) { + p->dead = 1; + } else { + p->w *= m; + } +} + +static f64 +next_step(f64 s) +{ + if (s < ZERO) { + f64 r = random_uniform(); + s = -log(r + EPS); + } + return s; +} + +static f64 +step_towards_boundary(Photon *p) +{ + f64 db; + if (p->dir.z < -ZERO) /* travel up */ + db = -p->pos.z / p->dir.z; + else if (p->dir.z > ZERO) /* travel down */ + db = (gctx.d - p->pos.z) / p->dir.z; + else + db = BIGVAL; + return db; +} + +static void +simulate_photon(Photon *p) +{ + f64 step = 0, boundary_dist = 0; + + launch_photon(p); + do { + step = next_step(step); + boundary_dist = step_towards_boundary(p); + if (boundary_dist * gctx.mu_t <= step) { + move_photon(p, boundary_dist); + step -= boundary_dist * gctx.mu_t; + reflect_or_transmit_photon(p); + } else { + move_photon(p, step / gctx.mu_t); + absorb_photon(p); + scatter_photon(p); + } + check_photon_life(p); + } while (!p->dead); +} + +int +main(int argc, char *argv[]) +{ + if (argc != 3) + die("usage: %s input_file output_file\n", argv[0]); + + load_input(argv[1]); + char *outfile = argv[2]; + + random_init(); + + alloc_mat2(&Rd_xy, gctx.Nx, gctx.Ny); + + /* Propagate Photons */ + time_t tstart, tend; + time(&tstart); + Photon p; + for (u32 i = 1; i <= gctx.N_photons; i++) { + simulate_photon(&p); + if (i % (gctx.N_photons / 10) == 0) + printf("[%u/%u] photons done!\n", i, gctx.N_photons); + } + time(&tend); + printf("Simulation took: %ld [s]\n", tend - tstart); + + + FILE *fd = fopen(outfile, "w"); + if (fd == NULL) + die("rip can't open output file: %s\n", outfile); + + fputs("/////////////Grid coordinates///////////\nx (cm): ", fd); + for (u32 i = 0; i < gctx.Nx; i++) + fprintf(fd, "%e ", (i + 0.5) * gctx.dx - gctx.xoff); + fputs("\ny (cm): ", fd); + for (u32 i = 0; i < gctx.Nx; i++) + fprintf(fd, "%e ", (i + 0.5) * gctx.dy - gctx.yoff); + fputs("\n/////////////////////////////////////////\n", fd); + fputs("///////////////Rd_xy/////////////////////\n", fd); + + f64 scale = gctx.N_photons * gctx.dx * gctx.dy; + f64 *b = Rd_xy.b; + for (u32 i = 0; i < Rd_xy.Nx; i++) { + for (u32 j = 0; j < Rd_xy.Ny; j++) + fprintf(fd, "%e ", b[j] / scale); + fputc('\n', fd); + b += Rd_xy.Ny; + } + fputs("\n/////////////////////////////////////////\n", fd); + fclose(fd); + + return 0; +} diff --git a/utils.cpp b/utils.cpp @@ -1,54 +0,0 @@ -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <time.h> - -#include "utils.h" - -static u64 rand_state[2]; - -void -random_init(void) -{ - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - rand_state[0] = (intptr_t)&printf ^ ts.tv_sec - ^ ((u64)ts.tv_nsec * 0xAC5533CD); - rand_state[1] = (intptr_t)&malloc ^ ts.tv_sec - ^ ((u64)ts.tv_nsec * 0xAC5533CD); -} - -static u64 -xoroshiro128plus(u64 s[2]) -{ - u64 s0 = s[0]; - u64 s1 = s[1]; - u64 result = s0 + s1; - s1 ^= s0; - s[0] = ((s0 << 24) | (s0 >> 40)) ^ s1 ^ (s1 << 16); - s[1] = (s1 << 37) | (s1 >> 27); - return result; -} - -double -random_uniform(void) -{ - return xoroshiro128plus(rand_state) / (double)UINT64_MAX; -} - -void -alloc_mat(struct Mat *m, int x, int y) -{ - if (x < 0 || y < 0) { - fputs("alloc_mat: dimensions must be positive\n", stderr); - exit(1); - } - - m->b = (double *)calloc(x * y, sizeof(double)); - if (m->b == NULL) { - fputs("malloc\n", stderr); - exit(1); - } - m->Nx = x; - m->Ny = y; -} diff --git a/utils.h b/utils.h @@ -1,60 +0,0 @@ -/* Providing global variables and functions*/ -#include <math.h> -#include <stdint.h> - -typedef uint64_t u64; -typedef uint32_t u32; - -//global constants -#define PI M_PI - -#ifndef ZERO - #define ZERO 1.0e-6 //for small deflection angle -#endif - -#ifndef n0 - #define n0 1.0 //refractive index of ambient medium -#endif - -#ifndef BIGVAL - #define BIGVAL 1e6//big value -#endif - -#define EPS 1.0e-9 - -//global variables -#ifdef GLOBALORIGIN - #define GLOBAL -#else - #define GLOBAL extern -#endif -GLOBAL double dx; -GLOBAL double dy; -GLOBAL int Nx; -GLOBAL int Ny; -GLOBAL double zc; -GLOBAL double n; -GLOBAL double mua; -GLOBAL double mus; -GLOBAL double mut; -GLOBAL double g; -GLOBAL double d; - -GLOBAL double th_in; // incident angle in degree - -GLOBAL double x_offset; -GLOBAL double y_offset; - -struct Mat { - u32 Nx, Ny; - double *b; -}; - -GLOBAL struct Mat Rd_xy; - -#define SIGN(x) ((x) >= 0 ? 1 : -1) - -void random_init(void); -double random_uniform(void); - -void alloc_mat(struct Mat *, int, int);