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 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 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 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; } }
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 } } } }