void IsotropicParticleMesher::_getSliceMask(int startidx, int endidx, Array3d<bool> &mask) { mask.fill(true); int width, height, depth; double dx; _getSubdividedGridDimensions(&width, &height, &depth, &dx); bool isStartSlice = startidx == 0; bool isEndSlice = endidx == width - 1; if (!isStartSlice) { int idx = 0; for (int k = 0; k < mask.depth; k++) { for (int j = 0; j < mask.height; j++) { mask.set(idx, j, k, false); } } } if (!isEndSlice) { int idx = mask.width - 1; for (int k = 0; k < mask.depth; k++) { for (int j = 0; j < mask.height; j++) { mask.set(idx, j, k, false); } } } }
void calculateChargesPotential(LSMSCommunication &comm, LSMSSystemParameters &lsms, LocalTypeInfo &local, CrystalParameters &crystal, int chargeSwitch) { Real *qsub; Array3d<Real> rhoTemp; //qsub = new Real[crystal.num_types]; qsub = (Real*)shmalloc(crystal.num_types*sizeof(Real)); for (int i=0; i<crystal.num_types; i++) qsub[i] = 0.0; rhoTemp.resize(lsms.global.iprpts+1, 2, local.num_local); rhoTemp = 0.0; printf("%d:calculateCharges\n",comm.comm.rank); calculateCharges(comm, lsms, local, crystal, qsub, rhoTemp, chargeSwitch); // for (int i=0; i<crystal.num_types; i++) printf("i, qsub = %5d %25.15f\n", i, qsub[i]); printf("%d:calculatePotential\n",comm.comm.rank); calculatePotential(comm, lsms, local, crystal, qsub, rhoTemp, chargeSwitch); printf("%d:end of calculatePotential\n",comm.comm.rank); //delete[] qsub; shfree(qsub); return; }
void DiffuseParticleSimulation::_removeDiffuseParticles() { Array3d<int> countGrid = Array3d<int>(_isize, _jsize, _ksize, 0); std::vector<bool> isRemoved; isRemoved.reserve(_diffuseParticles.size()); DiffuseParticle dp; GridIndex g; for (unsigned int i = 0; i < _diffuseParticles.size(); i++) { dp = _diffuseParticles[i]; if (dp.lifetime <= 0.0) { isRemoved.push_back(true); continue; } g = Grid3d::positionToGridIndex(dp.position, _dx); if (countGrid(g) >= _maxDiffuseParticlesPerCell) { isRemoved.push_back(true); continue; } countGrid.add(g, 1); isRemoved.push_back(false); } _removeItemsFromVector(_diffuseParticles, isRemoved); }
void create_dumbbell_signed_distance( const Vec3d& sphere_a_centre, const Vec3d& sphere_b_centre, double sphere_radius, double handle_width, double dx, const Vec3d& domain_low, const Vec3d& domain_high, Array3d& phi ) { phi.resize( (int) ceil( (domain_high[0]-domain_low[0]) / dx), (int) ceil( (domain_high[1]-domain_low[1]) / dx), (int) ceil( (domain_high[2]-domain_low[2]) / dx) ); std::cout << "Generating signed distance function. Grid resolution: " << phi.ni << " x " << phi.nj << " x " << phi.nk << std::endl; for ( int i = 0; i < phi.ni; ++i ) { for ( int j = 0; j < phi.nj; ++j ) { for ( int k = 0; k < phi.nk; ++k ) { Vec3d pt = domain_low + dx * Vec3d(i,j,k); phi(i,j,k) = signed_distance_dumbbell( pt, sphere_a_centre, sphere_b_centre, sphere_radius, handle_width ); } } } }
void create_cube_signed_distance( const Vec3d& cube_low, const Vec3d& cube_high, double dx, const Vec3d& domain_low, const Vec3d& domain_high, Array3d& phi ) { phi.resize( (int) ceil( (domain_high[0]-domain_low[0]) / dx), (int) ceil( (domain_high[1]-domain_low[1]) / dx), (int) ceil( (domain_high[2]-domain_low[2]) / dx) ); std::cout << "Generating signed distance function. Grid resolution: " << phi.ni << " x " << phi.nj << " x " << phi.nk << std::endl; for ( int i = 0; i < phi.ni; ++i ) { for ( int j = 0; j < phi.nj; ++j ) { for ( int k = 0; k < phi.nk; ++k ) { Vec3d pt = domain_low + dx * Vec3d(i,j,k); double dist_low_x = cube_low[0] - pt[0]; double dist_high_x = pt[0] - cube_high[0]; double dist_low_y = cube_low[1] - pt[1]; double dist_high_y = pt[1] - cube_high[1]; double dist_low_z = cube_low[2] - pt[2]; double dist_high_z = pt[2] - cube_high[2]; phi(i,j,k) = max( dist_low_x, dist_high_x, dist_low_y, dist_high_y, dist_low_z, dist_high_z ); } } } }
void create_capsule_signed_distance( const Vec3d& capsule_end_a, const Vec3d& capsule_end_b, double capsule_radius, double dx, const Vec3d& domain_low, const Vec3d& domain_high, Array3d& phi ) { phi.resize( (int) ceil( (domain_high[0]-domain_low[0]) / dx), (int) ceil( (domain_high[1]-domain_low[1]) / dx), (int) ceil( (domain_high[2]-domain_low[2]) / dx) ); std::cout << "Generating signed distance function. Grid resolution: " << phi.ni << " x " << phi.nj << " x " << phi.nk << std::endl; for ( int i = 0; i < phi.ni; ++i ) { for ( int j = 0; j < phi.nj; ++j ) { for ( int k = 0; k < phi.nk; ++k ) { Vec3d pt = domain_low + dx * Vec3d(i,j,k); double distance; Vec3d central_segment(capsule_end_b - capsule_end_a); double m2=mag2(central_segment); // find parameter value of closest point on infinite line double s = dot(capsule_end_b - pt, central_segment)/m2; if ( s < 0.0 ) { // dist = distance to the cylinder disc at end b distance = dist(pt, capsule_end_b); distance -= capsule_radius; } else if ( s > 1.0 ) { // dist = distance to the cylinder disc at end b distance = dist(pt, capsule_end_a ); distance -= capsule_radius; } else { // dist = distance to the cylinder's central axis distance = dist(pt, s*capsule_end_a + (1-s)*capsule_end_b); distance -= capsule_radius; } phi(i,j,k) = distance; } } } }
void TurbulenceField::_getVelocityGrid(MACVelocityField *macfield, Array3d<glm::vec3> &vgrid) { glm::vec3 v; for (int k = 0; k < vgrid.depth; k++) { for (int j = 0; j < vgrid.height; j++) { for (int i = 0; i < vgrid.width; i++) { v = macfield->evaluateVelocityAtCellCenter(i, j, k); vgrid.set(i, j, k, v); } } } }
void ScalarField::getSetScalarFieldValues(Array3d<bool> &isVertexSet) { FLUIDSIM_ASSERT(isVertexSet.width == _isVertexSet.width && isVertexSet.height == _isVertexSet.height && isVertexSet.depth == _isVertexSet.depth); for (int k = 0; k < isVertexSet.depth; k++) { for (int j = 0; j < isVertexSet.height; j++) { for (int i = 0; i < isVertexSet.width; i++) { isVertexSet.set(i, j, k, _isVertexSet(i, j, k)); } } } }
void ScalarField::getWeightField(Array3d<float> &field) { if (!_isWeightFieldEnabled) { return; } FLUIDSIM_ASSERT(field.width == _field.width && field.height == _field.height && field.depth == _field.depth); for (int k = 0; k < field.depth; k++) { for (int j = 0; j < field.height; j++) { for (int i = 0; i < field.width; i++) { field.set(i, j, k, _weightField(i, j, k)); } } } }
void LevelSet::_getLayerCells(int idx, std::vector<GridIndex> &layer, std::vector<GridIndex> &nextLayer, Array3d<int> &layerGrid) { GridIndex ns[6]; GridIndex g, n; for (unsigned int i = 0; i < layer.size(); i++) { g = layer[i]; _getNeighbourGridIndices6(g, ns); for (int j = 0; j < 6; j++) { n = ns[j]; if (Grid3d::isGridIndexInRange(n, _isize, _jsize, _ksize) && layerGrid(n) == -1) { nextLayer.push_back(n); layerGrid.set(n, idx); } } } }
void ScalarField::getScalarField(Array3d<float> &field) { FLUIDSIM_ASSERT(field.width == _field.width && field.height == _field.height && field.depth == _field.depth); double val; for (int k = 0; k < field.depth; k++) { for (int j = 0; j < field.height; j++) { for (int i = 0; i < field.width; i++) { val = _field(i, j, k); if (_isVertexSolid(i, j, k) && val > _surfaceThreshold) { val = _surfaceThreshold; } field.set(i, j, k, (float)val); } } } }
void calculateLocalCharges(LSMSSystemParameters &lsms, LocalTypeInfo &local, int chargeSwitch) { Array3d<Real> rhoTemp; rhoTemp.resize(lsms.global.iprpts+1, 2, local.num_local); // Compute integrated densities of states and store in xval** // (from mufind_c.f) for(int i=0; i<local.num_local; i++) { if (lsms.n_spin_cant == 2) // nspin >=3 { local.atom[i].qvalmt = local.atom[i].dosckint[0]; local.atom[i].qvalws = local.atom[i].dosint[0]; local.atom[i].mvalws = local.atom[i].dosint[1] * local.atom[i].evecNew[0] + \ local.atom[i].dosint[2] * local.atom[i].evecNew[1] + \ local.atom[i].dosint[3] * local.atom[i].evecNew[2]; local.atom[i].mvalmt = local.atom[i].dosckint[1] * local.atom[i].evecNew[0] + \ local.atom[i].dosckint[2] * local.atom[i].evecNew[1] + \ local.atom[i].dosckint[3] * local.atom[i].evecNew[2]; local.atom[i].xvalmt[0] = 0.5 * (local.atom[i].qvalmt + local.atom[i].mvalmt); local.atom[i].xvalwsNew[0] = 0.5 * (local.atom[i].qvalws + local.atom[i].mvalws); local.atom[i].xvalmt[1] = 0.5 * (local.atom[i].qvalmt - local.atom[i].mvalmt); local.atom[i].xvalwsNew[1] = 0.5 * (local.atom[i].qvalws - local.atom[i].mvalws); } else if (lsms.n_spin_pola == 2) // nspin = 2 { local.atom[i].qvalmt = local.atom[i].dosckint[0] + local.atom[i].dosckint[1]; local.atom[i].qvalws = local.atom[i].dosint[0] + local.atom[i].dosint[1]; local.atom[i].mvalmt = local.atom[i].dosckint[0] - local.atom[i].dosckint[1]; local.atom[i].mvalws = local.atom[i].dosint[0] - local.atom[i].dosint[1]; local.atom[i].xvalmt[0] = local.atom[i].dosckint[0]; local.atom[i].xvalwsNew[0] = local.atom[i].dosint[0]; local.atom[i].xvalmt[1] = local.atom[i].dosckint[1]; local.atom[i].xvalwsNew[1] = local.atom[i].dosint[1]; } else // nspin = 1 { local.atom[i].qvalmt = local.atom[i].dosckint[0]; local.atom[i].qvalws = local.atom[i].dosint[0]; local.atom[i].mvalmt = 0.0; local.atom[i].mvalws = 0.0; local.atom[i].xvalmt[0] = local.atom[i].dosckint[0]; local.atom[i].xvalwsNew[0] = local.atom[i].dosint[0]; } if (lsms.global.iprint > 0) { printf(" LOCAL WS Int[n(e)] = %18.11f\n", local.atom[i].qvalws); printf(" LOCAL MT Int[n(e)] = %18.11f\n", local.atom[i].qvalmt); printf(" LOCAL interstial Q = %18.11f\n", local.atom[i].qvalws - local.atom[i].qvalmt); if (lsms.n_spin_pola == 2) { printf(" LOCAL WS Int[m(e)] = %18.11f\n", local.atom[i].mvalws); printf(" LOCAL MT Int[m(e)] = %18.11f\n", local.atom[i].mvalmt); } printf(" LOCAL interstial M = %18.11f\n", local.atom[i].mvalws - local.atom[i].mvalmt); printf(" Spin = 1 LOCAL WS Int[n(e)] = %18.11f\n", local.atom[i].xvalwsNew[0]); printf(" Spin = 2 LOCAL WS Int[n(e)] = %18.11f\n", local.atom[i].xvalwsNew[1]); printf(" Spin = 1 LOCAL MT Int[n(e)] = %18.11f\n", local.atom[i].xvalmt[0]); printf(" Spin = 2 LOCAL MT Int[n(e)] = %18.11f\n", local.atom[i].xvalmt[1]); printf(" Spin = 1 LOCAL interstial Q = %18.11f\n", local.atom[i].xvalwsNew[0] - local.atom[i].xvalmt[0]); printf(" Spin = 2 LOCAL interstial Q = %18.11f\n", local.atom[i].xvalwsNew[1] - local.atom[i].xvalmt[1]); printf(" LOCAL Moment orientation = (%18.11f, %18.11f, %18.11f)\n", local.atom[i].evecNew[0], local.atom[i].evecNew[1], local.atom[i].evecNew[2]); } // Calculate qtotws and mtotws switch (chargeSwitch) { case 1: { local.atom[i].qtotws = local.atom[i].xvalws[0] + \ (lsms.n_spin_pola-1) * local.atom[i].xvalws[lsms.n_spin_pola-1] + \ local.atom[i].zsemss + \ local.atom[i].zcorss; local.atom[i].mtotws = local.atom[i].xvalws[0] - local.atom[i].xvalws[lsms.n_spin_pola-1]; break; } default: { local.atom[i].qtotws = local.atom[i].xvalwsNew[0] + \ (lsms.n_spin_pola-1) * local.atom[i].xvalwsNew[lsms.n_spin_pola-1] + \ local.atom[i].zsemss + \ local.atom[i].zcorss; local.atom[i].mtotws = local.atom[i].xvalwsNew[0] - local.atom[i].xvalwsNew[lsms.n_spin_pola-1]; } } // printf("qtotws = %12.8f\n", local.atom[i].qtotws); // printf("mtotws = %12.8f\n", local.atom[i].mtotws); // from genpot_c.f // ================================================================ // calculate qtotmt and mtotmt..................................... // ---------------------------------------------------------------- Real rSphere; switch (lsms.mtasa) { case 1: rSphere = local.atom[i].rws; break; case 2: rSphere = local.atom[i].rws; break; default: rSphere = local.atom[i].rInscribed; } Real *rTemp; rTemp = new Real[local.atom[i].jmt+3]; rTemp[0] = 0.0; for (int j=0; j<local.atom[i].jmt+2; j++) { //rTemp's indices need to be shifted by 1 for passing into getqm_mt! rTemp[j+1] = std::sqrt(local.atom[i].r_mesh[j]); } switch (chargeSwitch) { case 1: { if (local.atom[i].rhotot(local.atom[i].jmt,0) == 0.0) local.atom[i].rhotot(local.atom[i].jmt,0) = local.atom[i].rhotot(local.atom[i].jmt-1,0); if (local.atom[i].rhotot(local.atom[i].jmt+1,0) == 0.0) local.atom[i].rhotot(local.atom[i].jmt+1,0) = local.atom[i].rhotot(local.atom[i].jmt-1,0); if (local.atom[i].rhotot(local.atom[i].jmt,lsms.n_spin_pola-1) == 0.0) local.atom[i].rhotot(local.atom[i].jmt,lsms.n_spin_pola-1) = local.atom[i].rhotot(local.atom[i].jmt-1,lsms.n_spin_pola-1); if (local.atom[i].rhotot(local.atom[i].jmt+1,lsms.n_spin_pola-1) == 0.0) local.atom[i].rhotot(local.atom[i].jmt+1,lsms.n_spin_pola-1) = local.atom[i].rhotot(local.atom[i].jmt-1,lsms.n_spin_pola-1); if (lsms.global.iprint > 0) { printf("Spin = 1 rhotot[jmt-1], [jmt], [jmt+1] = %20.16f %20.16f %20.16f\n", local.atom[i].rhotot(local.atom[i].jmt-1,0), local.atom[i].rhotot(local.atom[i].jmt,0), local.atom[i].rhotot(local.atom[i].jmt+1,0)); printf("Spin = 2 rhotot[jmt-1], [jmt], [jmt+1] = %20.16f %20.16f %20.16f\n", local.atom[i].rhotot(local.atom[i].jmt-1,lsms.n_spin_pola-1), local.atom[i].rhotot(local.atom[i].jmt,lsms.n_spin_pola-1), local.atom[i].rhotot(local.atom[i].jmt+1,lsms.n_spin_pola-1)); } getqm_mt_(&lsms.n_spin_pola, &local.atom[i].jmt, &local.atom[i].rInscribed, rTemp, &local.atom[i].rhotot(0,0), &lsms.global.iprpts, &rhoTemp(0,0,i), &lsms.mtasa, &local.atom[i].qtotmt, &local.atom[i].mtotmt, &rSphere, &lsms.global.iprint); break; } default: { if (local.atom[i].rhoNew(local.atom[i].jmt,0) == 0.0) local.atom[i].rhoNew(local.atom[i].jmt,0) = local.atom[i].rhoNew(local.atom[i].jmt-1,0); if (local.atom[i].rhoNew(local.atom[i].jmt+1,0) == 0.0) local.atom[i].rhoNew(local.atom[i].jmt+1,0) = local.atom[i].rhoNew(local.atom[i].jmt-1,0); if (local.atom[i].rhoNew(local.atom[i].jmt,lsms.n_spin_pola-1) == 0.0) local.atom[i].rhoNew(local.atom[i].jmt,lsms.n_spin_pola-1) = local.atom[i].rhoNew(local.atom[i].jmt-1,lsms.n_spin_pola-1); if (local.atom[i].rhoNew(local.atom[i].jmt+1,lsms.n_spin_pola-1) == 0.0) local.atom[i].rhoNew(local.atom[i].jmt+1,lsms.n_spin_pola-1) = local.atom[i].rhoNew(local.atom[i].jmt-1,lsms.n_spin_pola-1); if (lsms.global.iprint > 0) { printf("Spin = 1 rhoNew[jmt-1], [jmt], [jmt+1] = %20.16f %20.16f %20.16f\n", local.atom[i].rhoNew(local.atom[i].jmt-1,0), local.atom[i].rhoNew(local.atom[i].jmt,0), local.atom[i].rhoNew(local.atom[i].jmt+1,0)); printf("Spin = 2 rhoNew[jmt-1], [jmt], [jmt+1] = %20.16f %20.16f %20.16f\n", local.atom[i].rhoNew(local.atom[i].jmt-1,lsms.n_spin_pola-1), local.atom[i].rhoNew(local.atom[i].jmt,lsms.n_spin_pola-1), local.atom[i].rhoNew(local.atom[i].jmt+1,lsms.n_spin_pola-1)); } getqm_mt_(&lsms.n_spin_pola, &local.atom[i].jmt, &local.atom[i].rInscribed, rTemp, &local.atom[i].rhoNew(0,0), &lsms.global.iprpts, &rhoTemp(0,0,i), &lsms.mtasa, &local.atom[i].qtotmt, &local.atom[i].mtotmt, &rSphere, &lsms.global.iprint); } } if (lsms.global.iprint >= 0) { printf("\n"); printf(" GENPOT / calculateLocalCharges: \n"); printf(" Total charge and moment in W-S cell:\n"); printf(" qtotws = %18.11f\n", local.atom[i].qtotws); printf(" mtotws = %18.11f\n", local.atom[i].mtotws); } delete[] rTemp; } }
int Analysis::writeData(Timing timing, double dt) { if (timing.check(dataOutputMoments, dt) ) { FA_Mom_Tp->write(getTemperatureParallel().data()); FA_Mom_HeatFlux->write(getHeatFlux().data()); FA_Mom_Density->write(getNumberDensity().data()); FA_Mom_Time->write(&timing); writeMessage("Data I/O : Moments output"); } if (timing.check(dataOutputStatistics, dt) ) { // Ugly and error-prone getPowerSpectrum(); Array2d pSpecX(Range(1, plasma->nfields), Range(0, Nx/2)); pSpecX(Range(1, plasma->nfields), Range(0, Nx/2)) = pSpec((int) DIR_X, Range(1, plasma->nfields), Range(0, Nx/2)); Array2d pSpecY(Range(1, plasma->nfields), Range(0, Nky)); pSpecY(Range(1, plasma->nfields), Range(0, Nky)) = pSpec((int) DIR_Y, Range(1, plasma->nfields), Range(0, Nky)); Array2d pPhaseX(Range(1, plasma->nfields), Range(0, Nx/2)); pPhaseX(Range(1, plasma->nfields), Range(0, Nx/2)) = pPhase((int) DIR_X, Range(1, plasma->nfields), Range(0, Nx/2)); Array2d pPhaseY(Range(1, plasma->nfields), Range(0, Nky)) ; pPhaseY(Range(1, plasma->nfields), Range(0, Nky)) = pPhase((int) DIR_Y, Range(1, plasma->nfields), Range(0, Nky)); FA_grow_x->write( pSpecX.data()); FA_grow_y->write( pSpecY.data()); FA_grow_t->write(&timing); FA_freq_x->write(pPhaseX.data()); FA_freq_y->write(pPhaseY.data()); FA_freq_t->write(&timing); // Heat Flux Array3d heatKy; heatKy.reference(getHeatFluxKy()); FA_heatKy->write(heatKy.data()); Array3d particleKy; particleKy.reference(getParticleFluxKy()); FA_particleKy->write(particleKy.data()); ScalarValues scalarValues; // calculate kineic Energy first, need for initial_e ! sum over sumdomains scalarValues.timestep = timing.step; scalarValues.time = timing.time; getFieldEnergy(scalarValues.phiEnergy, scalarValues.ApEnergy, scalarValues.BpEnergy); // Get scalar Values for every species for(int s = NsGlD; s <= NsGuD; s++) { scalarValues.particle_number[s-1] = getParticelNumber(s) ; scalarValues.entropy [s-1] = getEntropy(s) ; scalarValues.kinetic_energy [s-1] = getKineticEnergy(s) ; scalarValues.particle_flux [s-1] = getTotalParticleFlux(s) ; scalarValues.heat_flux [s-1] = getTotalHeatFlux(s) ; } SVTable->append(&scalarValues); // write out to Terminal/File std::stringstream messageStream; messageStream << "Step : " << scalarValues.timestep << " Time " << scalarValues.time << " Field : (phi)" << scalarValues.phiEnergy << " (Ap)" << scalarValues.ApEnergy << " (Bp) " << scalarValues.BpEnergy << std::endl; double charge = 0., kinetic_energy=0.; for(int s = NsGlD; s <= NsGuD; s++) { messageStream << plasma->species(s).name << " N :" << scalarValues.particle_number[s-1] << " Kinetic Energy : " << scalarValues.kinetic_energy[s-1] ; messageStream << " Particle Flux :" << scalarValues.particle_flux[s-1] << " Heat Flux : " << scalarValues.heat_flux[s-1] << std::endl; charge += plasma->species(s).q * scalarValues.particle_number[s-1]; kinetic_energy += scalarValues.kinetic_energy[s-1]; } messageStream << std::endl << "------------------------------------------------------------------" << std::endl << "Total Energy " << kinetic_energy+scalarValues.phiEnergy + scalarValues.ApEnergy + scalarValues.BpEnergy << " Total Charge = " << ((plasma->species(0).n0 != 0.) ? 0. : charge) << std::endl; parallel->print(messageStream); } return HELIOS_SUCCESS; }
void make_level_set3(const std::vector<Vec3ui> &tri, const std::vector<Vec3d> &x, const Vec3d &origin, double dx, int ni, int nj, int nk, Array3d &phi, Array3i& closest_tri, const int exact_band ) { phi.resize(ni, nj, nk); phi.assign((ni+nj+nk)*dx); // upper bound on distance closest_tri.clear(); closest_tri.resize(ni, nj, nk, -1); Array3i intersection_count(ni, nj, nk, 0); // intersection_count(i,j,k) is # of tri intersections in (i-1,i]x{j}x{k} // we begin by initializing distances near the mesh, and figuring out intersection counts Vec3d ijkmin, ijkmax; for(unsigned int t=0; t<tri.size(); ++t){ unsigned int p, q, r; assign(tri[t], p, q, r); // coordinates in grid to high precision double fip=((double)x[p][0]-origin[0])/dx, fjp=((double)x[p][1]-origin[1])/dx, fkp=((double)x[p][2]-origin[2])/dx; double fiq=((double)x[q][0]-origin[0])/dx, fjq=((double)x[q][1]-origin[1])/dx, fkq=((double)x[q][2]-origin[2])/dx; double fir=((double)x[r][0]-origin[0])/dx, fjr=((double)x[r][1]-origin[1])/dx, fkr=((double)x[r][2]-origin[2])/dx; // do distances nearby int i0=clamp(int(min(fip,fiq,fir))-exact_band, 0, ni-1), i1=clamp(int(max(fip,fiq,fir))+exact_band+1, 0, ni-1); int j0=clamp(int(min(fjp,fjq,fjr))-exact_band, 0, nj-1), j1=clamp(int(max(fjp,fjq,fjr))+exact_band+1, 0, nj-1); int k0=clamp(int(min(fkp,fkq,fkr))-exact_band, 0, nk-1), k1=clamp(int(max(fkp,fkq,fkr))+exact_band+1, 0, nk-1); for(int k=k0; k<=k1; ++k) for(int j=j0; j<=j1; ++j) for(int i=i0; i<=i1; ++i){ Vec3d gx(i*dx+origin[0], j*dx+origin[1], k*dx+origin[2]); double d=point_triangle_distance(gx, x[p], x[q], x[r]); if(d<phi(i,j,k)){ phi(i,j,k)=d; closest_tri(i,j,k)=t; } } // and do intersection counts j0=clamp((int)std::ceil(min(fjp,fjq,fjr)), 0, nj-1); j1=clamp((int)std::floor(max(fjp,fjq,fjr)), 0, nj-1); k0=clamp((int)std::ceil(min(fkp,fkq,fkr)), 0, nk-1); k1=clamp((int)std::floor(max(fkp,fkq,fkr)), 0, nk-1); for(int k=k0; k<=k1; ++k) for(int j=j0; j<=j1; ++j){ double a, b, c; if(point_in_triangle_2d(j, k, fjp, fkp, fjq, fkq, fjr, fkr, a, b, c)){ double fi=a*fip+b*fiq+c*fir; // intersection i coordinate int i_interval=int(std::ceil(fi)); // intersection is in (i_interval-1,i_interval] if(i_interval<0) ++intersection_count(0, j, k); // we enlarge the first interval to include everything to the -x direction else if(i_interval<ni) ++intersection_count(i_interval,j,k); // we ignore intersections that are beyond the +x side of the grid } } } // and now we fill in the rest of the distances with fast sweeping for(unsigned int pass=0; pass<2; ++pass){ sweep(tri, x, phi, closest_tri, origin, dx, +1, +1, +1); sweep(tri, x, phi, closest_tri, origin, dx, -1, -1, -1); sweep(tri, x, phi, closest_tri, origin, dx, +1, +1, -1); sweep(tri, x, phi, closest_tri, origin, dx, -1, -1, +1); sweep(tri, x, phi, closest_tri, origin, dx, +1, -1, +1); sweep(tri, x, phi, closest_tri, origin, dx, -1, +1, -1); sweep(tri, x, phi, closest_tri, origin, dx, +1, -1, -1); sweep(tri, x, phi, closest_tri, origin, dx, -1, +1, +1); } // then figure out signs (inside/outside) from intersection counts for(int k=0; k<nk; ++k) for(int j=0; j<nj; ++j){ int total_count=0; for(int i=0; i<ni; ++i){ total_count+=intersection_count(i,j,k); if(total_count%2==1){ // if parity of intersections so far is odd, phi(i,j,k)=-phi(i,j,k); // we are inside the mesh } } } }