C/C++


Program Bubble Packing

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <math.h>
#include <vector>
#include <cstring>
#include <fstream>
#define pi  3.14159265358979323846264338327950288419716939937510
#define ntmax 50000
int every = 25;

using namespace std;

typedef struct{
    double x;
    double y;
} Vec_2D;

typedef struct{
    Vec_2D pos;
    Vec_2D force;
    Vec_2D v;
    double diameter;
    int state;
}Buble;

typedef std::vector<Buble> Vbuble;

enum{fixbuble, freebuble};

double const c = 0.03; //edit
double const m = 1.7;
double const eps = 0.0034; //edit
double const diam_free_buble = 0.0126; //edit
double const diam_fix_buble = 0.0064; //edit
double const tol_dist = 1.16*diam_free_buble;
double const k0 = 1./(m)*pow(c/(2*0.7),2);
int Nbuble;
int Nfixbuble;
int Nfreebuble;
int nt = 1;
//-------------------------------------------------------------------------------------------------------
Buble* Initial_Probe_Position(int* n) {
    Buble buble;
    Vbuble bub_tmp;
    int k = 0;
    string line;
    ifstream inputfile;
    inputfile.open("initial_buble_position.txt");
    char datanum[30];
    while (!inputfile.eof()) {
        getline(inputfile,line);
        if (line.length() != 0 && line[0] != '#') {
      strcpy(datanum,line.c_str());
      sscanf(datanum, "%lf %lf %lf %lf %d", &buble.pos.x, &buble.pos.y, &buble.v.x, &buble.v.y, &buble.state);
    }
    if (buble.state == 0) {
                buble.diameter = diam_fix_buble;
                k++;
        } else buble.diameter = diam_free_buble;
    bub_tmp.push_back(buble);
    }
    inputfile.close();
    Nbuble = bub_tmp.size();
    Nfixbuble = k;
    Nfreebuble = Nbuble - Nfixbuble;
    (*n) = bub_tmp.size();
    printf("#buble = %d\n",(*n));
    Buble* buble_p = new Buble[(*n)];
    for(int i = 0; i < (*n); i++){
        buble_p[i] = bub_tmp[i];
    }
    bub_tmp.clear();
    return buble_p;
}

double Buble_Distance(Buble b1, Buble b2){
    return sqrt(pow(b1.pos.x-b2.pos.x,2) + pow(b1.pos.y-b2.pos.y,2));
}

Vec_2D Vec_Inbuble_Direction(Buble b1, Buble b2) {
    double r = Buble_Distance(b1,b2);
    Vec_2D ibf;
    ibf.x = (b2.pos.x - b1.pos.x)/r;
    ibf.y = (b2.pos.y - b1.pos.y)/r;
    return ibf;
}

double Angle_of_Force(Buble b1, Buble b2) {
    Vec_2D ibf = Vec_Inbuble_Direction(b1,b2);
    double theta;
    theta = atan2(ibf.y, ibf.x);
    theta = (theta < 0 ? 2*pi + theta : theta);
    return theta;
}

double Interbubble_Force(Buble b1, Buble b2) {
    double r = Buble_Distance(b1,b2);
    double r0 = 0.5*b1.diameter + 0.5*b2.diameter;
    double w = r/r0;
    double f = 0.;
    if (w >= 0 && w <= 1.5)
        f = 1.25*k0/r0*pow(w,3) - 2.375*k0/r0*pow(w,2) + 1.125*k0/r0;
    else f = 0.;
    return f;
}

void compute_f(const vector<double> &x_vector, vector<double> &f_vector, double f_ext){
    //double x1 = x_vector[0];
    double x2 = x_vector[1];
    f_vector[0] = x2;
    f_vector[1] = -c/m*x2 + 1./m*f_ext;
}

//4th order Runge-Kutta
Vec_2D Runge_Kutta_4(vector<double> &x_vector, double f_ext, double tf){
    Vec_2D vecx;
    double t0 = 0.;
    double dt = 1.e-4;
    //double t = t0;
    int m = (tf-t0)/dt;
    //------------------------------------------------------
    int n = x_vector.size();
    vector<double> x(n), f(n), k1(n), k2(n), k3(n), k4(n);
    for (int i=1; i <= m+1; i++){
        compute_f(x_vector,f,f_ext);
        for(int i=0; i < n; i++)
            k1[i] = dt*f[i];

        for(int i=0; i < n; i++)
            x[i] = x_vector[i] + 0.5*k1[i];
        compute_f(x,f,f_ext);
        for(int i=0; i < n; i++)
            k2[i] = dt*f[i];

        for(int i=0; i < n; i++)
            x[i] = x_vector[i] + 0.5*k2[i];
        compute_f(x,f,f_ext);
        for(int i=0; i < n; i++)
            k3[i] = dt*f[i];

        for(int i=0; i < n; i++)
            x[i] = x_vector[i] + k3[i];
        compute_f(x,f,f_ext);
        for(int i=0; i < n; i++)
            k4[i] = dt*f[i];

        for(int i=0; i < n; i++)
            x_vector[i] += (k1[i] + 2*k2[i] + 2*k3[i] + k4[i])/6.;
    }
    vecx.x = x[0];
    vecx.y = x[1];
    return vecx;
}

void Sum_Buble_Force(Buble *buble, int Nb) {
    double r0;
    for (int i = 0; i < Nb; i++) {
        if (buble[i].state == freebuble) {
            //printf("i = %d free %d\n", i, buble[i].state);
            double sumfx = 0.;
            double sumfy = 0.;
            double theta = 0.;
            double r;
            for (int j = 0; j < Nb; j++) {
                if (i != j) {
                    r = Buble_Distance(buble[i], buble[j]);
                    r0 = 0.5*buble[i].diameter + 0.5*buble[j].diameter;
                    theta = Angle_of_Force(buble[i],buble[j]);
                    if (r/r0 > 1.) {
                        sumfx += fabs(Interbubble_Force(buble[i],buble[j]))*(cos(theta));
                        sumfy += fabs(Interbubble_Force(buble[i],buble[j]))*(sin(theta));
                    } else {
                        sumfx += -1*fabs(Interbubble_Force(buble[i],buble[j]))*(cos(theta));
                        sumfy += -1*fabs(Interbubble_Force(buble[i],buble[j]))*(sin(theta));
                    }
                }
            }
            buble[i].force.x = sumfx;
            buble[i].force.y = sumfy;
        }
    }
}

void New_Buble_Position(Buble *buble, double t, int Nb) {
    vector<double> x(2);
    vector<double> y(2);
    Vec_2D fext;
    Vec_2D vecx, vecy;
    for (int i=0; i < Nb; i++) {
        if (buble[i].state == freebuble) {
            x[0] = buble[i].pos.x;
            x[1] = buble[i].v.x;
            fext.x = buble[i].force.x;
            vecx = Runge_Kutta_4(x, fext.x, t);
            buble[i].pos.x = vecx.x;
            buble[i].v.x = vecx.y;

            y[0] = buble[i].pos.y;
            y[1] = buble[i].v.y;
            fext.y = buble[i].force.y;
            vecy = Runge_Kutta_4(y, fext.y, t);
         }
    }
}

int Stop_Searching(Buble const *buble, double eps, int Nb) {
    int Nf = Nfreebuble;
    int stop[Nf*(Nf-1)/2] = {0};
    int keluar = 0;
    int hit = 0;
    int k = 0;
    double f = 0.;
    double d;
    for (int i = Nfixbuble; i < Nb-1; i++) {
        for (int j = i+1; j < Nb; j++) {
            f = Interbubble_Force(buble[i], buble[j]);
            d = Buble_Distance(buble[i],buble[j]);
            if (((fabs(f) <= eps) && (fabs(f) >= 0.)) || ((d > 1.00*diam_free_buble) && (d < tol_dist))) {
                stop[k] = 1;
                printf("f%d-%d = %8.6lf stabil\n", i-Nfixbuble+1, j-Nfixbuble+1, fabs(f));
                k++;
            } else printf("f%d-%d = %8.6lf tidak stabil\n", i-Nfixbuble+1, j-Nfixbuble+1, fabs(f));
        }
    }
    for (int i = 0; i < k; i++) {
        if (stop[i] == 1) hit++;
        //printf("%d ", stop[i]);
    }
    if (hit == Nf*(Nf-1)/2) keluar = 1;
    printf("buble stabil = %d || target buble stabil = %d\n", hit, Nf*(Nf-1)/2);
    return keluar;
}

void read_data_points(FILE* fp, double* x, double* y, int n){
    for(int i = 0; i <= n-1; i++){
        fscanf(fp, "%lf %lf", &(x[i]), &(y[i]));
    }
}

void set_gnuplot_condition(FILE* gp)
{
    fprintf(gp, "set xrange [%g:%g]\n", 0.33, 0.38);
    fprintf(gp, "set yrange [%g:%g]\n", 0.17, 0.23);
    fprintf(gp, "set xtics 0.01\n");
    fprintf(gp, "unset mouse\n");
    fprintf(gp, "set term x11\n");
    fprintf(gp, "set size ratio -1\n");
}

void plot_buble(FILE* gp, Buble const* buble, double* x1, double* y1, int n1, int n, int Nb)
{
    fprintf(gp, "set title \"iteration = %d\"\n", n);
    fprintf(gp, "plot \"-\" with circles lc rgb \"blue\" fs transparent solid 0.1 border notitle, \"-\" w p lt 2 notitle\n");
    for (int i=0; i < Nb; i++) {
        //if (buble[i].state == freebuble)
            fprintf(gp, "%f %f %f\n", buble[i].pos.x, buble[i].pos.y, 0.5*buble[i].diameter);
    }
    fprintf(gp, "e\n");
    for (int i = 0; i <= n1-1; i++){
        fprintf(gp, "%f %f\n", x1[i], y1[i]);
    }
    fflush(gp);
}

void Save_Buble(Buble const* buble, int Nb) {
    FILE *file;
    file=fopen("buble_position_optimal.txt","w");
    fprintf(file, "#iteration = %d\n", nt-1);
    fprintf(file, "#total buble = %d || fixbuble = %d || freebuble = %d\n", Nb, Nfixbuble, Nfreebuble);
    fprintf(file, "#diameter fix buble = %10.6lf || diameter free buble = %10.6lf\n", diam_fix_buble, diam_free_buble);
    fprintf(file,"#m = %4.2lf  || c = %4.2lf  || eps = %10.6lf || k0 = %10.6lf\n", m, c, eps, k0);
    for (int i=0; i < Nb; i++) {
        if (buble[i].state == freebuble) fprintf(file, "%8.6lf %8.6lf %8.6lf %8.6lf\n", buble[i].pos.x, buble[i].pos.y, 0.5*buble[i].diameter, 0.003);
    }
    fclose(file);
}

void save2file (Buble const* buble, int n, int Nb){
    FILE *fp;
    char filename[32];
    sprintf(filename, "output%.4d.dat", n/every);
    fp=fopen(filename,"w");
    fprintf(fp, "#iteration = %d\n", n);
    for (int i=0; i < Nb; i++) {
        if (buble[i].state == freebuble)
            fprintf(fp, "%f %f %f\n", buble[i].pos.x, buble[i].pos.y, 0.5*buble[i].diameter);
    }
    fclose(fp);
}

void save2gnuplot (int nt){
     FILE *plot;
     plot=fopen("buble_packing_animation.gp","w");
     for (int n = 1; n <= nt/every; n++){
        fprintf(plot,"reset\n");
        fprintf(plot,"set terminal pngcairo  background \"#ffffff\" enhanced fontscale 1.0 size 640, 480  dashlength 2\n");
        fprintf(plot,"set output \"figure%.4d.png\"\n", n);
        fprintf(plot,"set size ratio -1\n");
        fprintf(plot,"set style line 1  linecolor rgb \"orange\"  linewidth 2.000 dashtype 1 pointtype 2 pointsize default pointinterval 0\n");
        fprintf(plot,"set style line 2  linecolor rgb \"blue\"  linewidth 2.000 dashtype 1 pointtype 2 pointsize default pointinterval 0\n");
        fprintf(plot, "set xrange [%g:%g]\n", 0.33, 0.38);
        fprintf(plot, "set yrange [%g:%g]\n", 0.17, 0.23);
        fprintf(plot, "set xtics 0.01\n");
        fprintf(plot, "unset mouse\n");
        fprintf(plot,"set xlabel \"x (m)\"\n");
        fprintf(plot,"set ylabel \"y (m)\"\n");
        fprintf(plot, "set title \"#iteration = %d\"\n", n*every);
        fprintf(plot, "plot \"output%.4d.dat\" with circles lc rgb \"blue\" fs transparent solid 0.1 border notitle, \"\" with points notitle, \"lungcancer.txt\" w l ls 2 notitle\n",n);
        fprintf(plot,"\n");
     }
     fclose(plot);
}
//----------------------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    FILE* gp  = popen("gnuplot > /dev/null 2>&1", "w");
    set_gnuplot_condition(gp);
    //----------------------------------------------------------------
    FILE* fp1 = fopen("lungcancer.txt", "r");
    int const n1 = 1484;
    double *x1 =    new double[n1];
    double *y1 =    new double[n1];
    read_data_points(fp1, x1, y1, n1);
    //----------------------------------------------------------------
    /*for (int i=0; i<n1; i++){
        if (i % 20 == 0) printf("%7.6lf %7.6lf %d %d %d\n", x1[i], y1[i], 0, 0, 0);
    }*/
    int Nb = 0;
    Buble *buble = Initial_Probe_Position(&Nb);
    int stop = 0;
    double dt = 1.e-3;
    //----------------------------------------------------------------
    plot_buble(gp, buble, x1, y1, n1, nt, Nb);
    while ((stop == 0) && (nt <= ntmax)) {
        printf("n = %d\n", nt);
        Sum_Buble_Force(buble, Nb);
        New_Buble_Position(buble, dt, Nb);
        //plot_buble(gp, buble, x1, y1, n1, nt, Nb);
        stop = Stop_Searching(buble, eps, Nb);
        if (nt % every == 0) save2file(buble,nt,Nb);
        nt++;
        printf("--------------------------------------------------\n");
    }
    Save_Buble(buble, Nb);
    save2gnuplot(nt-1);
    delete[] buble;
    return 0;
}