{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multi-Scale Simulation "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Amira Abdel-Rahman\n",
    "# (c) Massachusetts Institute of Technology 2021"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [],
   "source": [
    "# JULIA 1.2.0\n",
    "using EnhancedGJK ,GeometryTypes,LinearAlgebra,BenchmarkTools;\n",
    "# make sure MeshIO is old version (0.3.2) to use geometry types and not gemoetry basics\n",
    "using MeshIO ,FileIO,CoordinateTransformations,MeshCat,RegionTrees;\n",
    "\n",
    "# using GeometryBasics\n",
    "\n",
    "import StaticArrays: SVector\n",
    "import JSON\n",
    "\n",
    "using Plots\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: replacing module AdaptivelySampledDistanceFields.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "pointInsideVoxelGrid (generic function with 1 method)"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "include(\"../julia/include/asdf/adaptive_distance_fields.jl\")\n",
    "using .AdaptivelySampledDistanceFields\n",
    "include(\"../julia/include/asdf/reference_distance.jl\")\n",
    "include(\"../julia/include/asdf/asdf_functions.jl\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Import Mesh and SDF Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [],
   "source": [
    "## if convex mesh\n",
    "# origin = SVector(-10., -3., -12)\n",
    "# widths = SVector(24., 24, 24)\n",
    "\n",
    "# insideOnly=true\n",
    "\n",
    "# maxDivision=5 #how many divisions\n",
    "# minDivision=6 #how many divisions\n",
    "\n",
    "\n",
    "# minSize=widths[1]/(2^minDivision) #min voxel size\n",
    "# maxSize=widths[1]/(2^maxDivision) #max voxel size\n",
    "# atol=minSize*widths[1]/2*0.1\n",
    "# println(\"Min Vox Size=$(minSize),Max Vox Size=$(maxSize), atol=$(atol)\")\n",
    "\n",
    "# rtol=0.0\n",
    "# adaptive = AdaptivelySampledDistanceFields.ASDF(sWing, origin, widths, tol1, tol2)\n",
    "# boxmesh=getVisQuadtree(adaptive,true, sdfWing)\n",
    "# save(\"../CAD/WingMultiscale.stl\", boxmesh)\n",
    "\n",
    "# orderedCones1=getOrderedBins(adaptive, sdfCone);\n",
    "# stringdata = JSON.json(orderedCones1)\n",
    "# fileName=(\"./json/Sphere/orderedCones1.json\")\n",
    "# open(fileName, \"w\") do f\n",
    "#         write(f, stringdata)\n",
    "# end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 178,
   "metadata": {},
   "outputs": [],
   "source": [
    "wing =load(\"../julia/examples/CAD_Rhino/wing_rot.stl\")\n",
    "\n",
    "resolution=128*2\n",
    "mesh=wing\n",
    "empty=false\n",
    "voxels,verts_min,verts_max=_voxelize(mesh, resolution,empty);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 179,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Min Vox Size=1.5,Max Vox Size=0.75, atol=1.8\n"
     ]
    }
   ],
   "source": [
    "origin = SVector(-10., -4., -12)\n",
    "widths = SVector(24., 24, 24)\n",
    "\n",
    "w=widths[1]\n",
    "\n",
    "insideOnly=true\n",
    "\n",
    "maxDivision=5 #how many divisions\n",
    "minDivision=4 #how many divisions\n",
    "\n",
    "\n",
    "minSize=w/(2^minDivision) #min voxel size\n",
    "maxSize=w/(2^maxDivision) #max voxel size\n",
    "\n",
    "atol=minSize*w/2*0.1 \n",
    "rtol=0.0\n",
    "\n",
    "println(\"Min Vox Size=$(minSize),Max Vox Size=$(maxSize), atol=$(atol)\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 180,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "#859 (generic function with 1 method)"
      ]
     },
     "execution_count": 180,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# s_wing=ReferenceDistance.signed_distance(wing)\n",
    "sdfWing=signed_distance1(wing)\n",
    "sWing=adjustedSignedDistance(wing) #use this when convex mesh\n",
    "\n",
    "sWingConcave=signedDistanceConcave(wing,voxels,resolution,verts_min,verts_max) \n",
    "sExWingConcave=exteriorDistanceConcave(wing,voxels,resolution,verts_min,verts_max) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 181,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inside:9120\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "13"
      ]
     },
     "execution_count": 181,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "adaptive = AdaptivelySampledDistanceFields.ASDF(sExWingConcave, origin, widths, rtol, atol2,maxSize)\n",
    "# adaptive = AdaptivelySampledDistanceFields.ASDF(sWing, origin, widths, rtol, atol,maxSize)\n",
    "# adaptive = AdaptivelySampledDistanceFields.ASDF(sWingConcave, origin, widths, rtol, atol,maxSize)\n",
    "\n",
    "boxmesh=getVisQuadtreeNonConvex(adaptive,insideOnly,voxels,resolution,verts_min,verts_max)\n",
    "save(\"../CAD/WingMultiscale1.stl\", boxmesh)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Export Voxels/cubes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Real Min Vox Size=0.375,Max Vox Size=0.75\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3-element Array{Float64,1}:\n",
       "  0.3125\n",
       " -2.3125\n",
       " -0.9375"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cubes=[]\n",
    "count=0\n",
    "for leaf in allleaves(adaptive.root)\n",
    "    for face in RegionTrees.faces(leaf.boundary)\n",
    "        p=(RegionTrees.center(leaf.boundary))\n",
    "        pointX=Int(round(p[1],digits=0)); pointY=Int(round(p[2],digits=0)); pointZ=Int(round(p[3],digits=0))\n",
    "        if pointInsideVoxelGrid([p[1] p[2] p[3]],voxels,resolution,verts_min,verts_max)     #println(leaf.boundary.widths)\n",
    "            append!(cubes,[leaf.boundary])\n",
    "        end\n",
    "        count+=1\n",
    "    end\n",
    "end\n",
    "cubes=unique(cubes)\n",
    "\n",
    "sort!(cubes, by = x -> x.widths[2]);\n",
    "minSize=cubes[1].widths[1]\n",
    "maxSize=cubes[end].widths[1]\n",
    "println(\"Real Min Vox Size=$(minSize),Max Vox Size=$(maxSize)\")\n",
    "\n",
    "sort!(cubes, by = x -> x.origin[1]);\n",
    "minOrigin1=cubes[1].origin[1]\n",
    "\n",
    "sort!(cubes, by = x -> x.origin[2]);\n",
    "minOrigin2=cubes[1].origin[2]\n",
    "\n",
    "sort!(cubes, by = x -> x.origin[3]);\n",
    "minOrigin3=cubes[1].origin[3]\n",
    "\n",
    "minOrigin=[minOrigin1,minOrigin2,minOrigin3].+minSize/2.0\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [],
   "source": [
    "voxs=[]\n",
    "for cube in cubes\n",
    "    size=cube.widths[1]/minSize\n",
    "    append!(voxs,[[((cube.origin.-minOrigin)./minSize .+(0.5*size)) ,[size]]])\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run Simulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded MetaVoxels Functions!\n"
     ]
    }
   ],
   "source": [
    "plotting=false\n",
    "GPU=false\n",
    "logging=true\n",
    "include(\"../julia/MetaVoxels.jl\") #load MetaVoxels!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Desired Min Vox Size=0.375,Max Vox Size=0.75, atol=0.45"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: replacing module AdaptivelySampledDistanceFields.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Real Min Vox Size=0.375,Max Vox Size=0.75\n"
     ]
    }
   ],
   "source": [
    "include(\"../julia/examples/multiscale/meshtoASDFvoxel.jl\") #multiscale\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loaded MetaVoxels Functions!\n",
      "Success! Created structure with 2624 nodes and 3953 edges.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Process(`\u001b[4mnode\u001b[24m \u001b[4m../node/app1.js\u001b[24m \u001b[4mtutorial\u001b[24m`, ProcessExited(0))"
      ]
     },
     "execution_count": 167,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "simName=\"tutorial\"\n",
    "\n",
    "include(\"../julia/examples/multiscale/meshMultiscale.jl\") #multiscale\n",
    "\n",
    "## recompile these just for sanity check for dynamic loads\n",
    "include(\"../julia/MetaVoxels.jl\") \n",
    "\n",
    "#export setup using nodejs and javascript from \"./json/$(simName)Init.json\" and save to \"./json/$(simName).json\"\n",
    "exportJuliaSettingsUsingNode(setup,simName)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dt: 1.4235251564292887e-5, s: 0.001, mass: 8.0e-6, momentInertiaInverse: 1.8749999999999997e11\n",
      "first timestep took 0.6208143 seconds\n",
      "ran 2624 nodes and 3953 edges for 1000 time steps took 10.5526276 seconds\n"
     ]
    }
   ],
   "source": [
    "#detailed\n",
    "setupSim1=getSetup(simName); #get simulation from\"./json/$(simName).json\"\n",
    "savedDataFolderPath=\"../json/$(simName)/\" # make sure this folder exists, this is where the simulation result will be saved\n",
    "runMetaVoxels!(setupSim1,savedDataFolderPath,\"CPU\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 176,
   "metadata": {},
   "outputs": [],
   "source": [
    "count=0\n",
    "for node in setupSim1[\"nodes\"]\n",
    "    if node[\"parent\"]==\"\"\n",
    "        count+=1\n",
    "    end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 177,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1520"
      ]
     },
     "execution_count": 177,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": null,
   "lastKernelId": null
  },
  "kernelspec": {
   "display_name": "Julia 1.2.0",
   "language": "julia",
   "name": "julia-1.2"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.2.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}