Пример #1
0
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 ); 
                
            }
        }
    }
}
Пример #2
0
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;
}
Пример #4
0
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;

  }
}
Пример #6
0
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
         }
      }
   }
}