示例#1
0
class PhysicalSystem(Matter):
    def __init__(self,
                 structure=None,
                 net_charge=0,
                 net_spin=0,
                 particles=None,
                 **valency):
        self.pseudized = False

        if structure is None:
            self.structure = Structure()
        else:
            self.structure = structure
        #end if
        if particles is None:
            self.particles = Particles()
        else:
            self.particles = particles.copy()
        #end if

        self.folded_system = None
        if self.structure.has_folded():
            if self.structure.is_tiled():
                vratio = structure.volume(
                ) / structure.folded_structure.volume()
                ncells = int(round(vratio))
                if abs(vratio - ncells) > 1e-4:
                    self.error(
                        'volume of system does not divide evenly into folded system'
                    )
                #end if
                if net_charge % ncells != 0:
                    self.error(
                        'net charge of system does not divide evenly into folded system'
                    )
                #end if
                if isinstance(net_spin, str):
                    net_spin_fold = net_spin
                elif net_spin % ncells != 0:
                    self.error(
                        'net_spin of system does not divide evenly into folded system'
                    )
                else:
                    net_spin_fold = net_spin // ncells
                #end if
                net_charge_fold = net_charge // ncells
            elif not self.structure.has_axes():  # folded molecule
                # net charge/spin are not physically meaningful
                # for a point group folded molecule
                # set them to safe values; they will not be used later
                net_charge_fold = 0
                net_spin_fold = 'low'
            else:
                self.error(
                    'folded structure is not correctly integrated with full structure\nfolded physical system cannot be constructed'
                )
            #end if

            self.folded_system = PhysicalSystem(
                structure=structure.folded_structure,
                net_charge=net_charge_fold,
                net_spin=net_spin_fold,
                particles=particles,
                **valency)
        #end if

        self.valency_in = obj(**valency)
        self.net_charge_in = net_charge
        self.net_spin_in = net_spin

        self.update_particles(clear=False)

        self.check_folded_system()

    #end def __init__

    def update_particles(self, clear=True):
        #add ions
        pc = dict()
        elem = list(self.structure.elem)
        for ion in set(elem):
            pc[ion] = elem.count(ion)
        #end for
        missing = set(pc.keys()) - set(self.particles.keys())
        if len(missing) > 0 or len(elem) == 0:
            if clear:
                self.particles.clear()
            #end if
            self.add_particles(**pc)

            #pseudize
            if len(self.valency_in) > 0:
                self.pseudize(**self.valency_in)
            #end if

            #add electrons
            self.generate_electrons(self.net_charge_in, self.net_spin_in)
        #end if

    #end def update_particles

    def update(self):
        self.net_charge = self.structure.background_charge
        self.net_spin = 0
        for p in self.particles:
            self.net_charge += p.count * p.charge
            self.net_spin += p.count * p.spin
        #end for
        self.net_charge = int(round(float(self.net_charge)))
        self.net_spin = int(round(float(self.net_spin)))

    #end def update

    def add_particles(self, **particle_counts):
        pc = self.particle_collection  # all known particles
        plist = []
        for name, count in particle_counts.items():
            particle = pc.get_particle(name)
            if particle is None:
                self.error('particle {0} is unknown'.format(name))
            else:
                particle = particle.copy()
            #end if
            particle.set_count(count)
            plist.append(particle)
        #end for
        self.particles.add_particles(plist)
        self.update()

    #end def add_particles

    def generate_electrons(self, net_charge=0, net_spin=0):
        nelectrons = -net_charge + self.net_charge
        if net_spin == 'low':
            net_spin = nelectrons % 2
        #end if
        nup = float(nelectrons + net_spin - self.net_spin) / 2
        ndown = float(nelectrons - net_spin + self.net_spin) / 2
        if abs(nup - int(nup)) > 1e-3:
            self.error(
                'requested spin state {0} incompatible with {1} electrons'.
                format(net_spin, nelectrons))
        #end if
        nup = int(nup)
        ndown = int(ndown)
        self.add_particles(up_electron=nup, down_electron=ndown)

    #end def generate_electrons

    def pseudize(self, **valency):
        errors = False
        for ion, valence_charge in valency.items():
            if ion in self.particles:
                ionp = self.particles[ion]
                if isinstance(ionp, Ion):
                    self.particles[ion] = ionp.pseudize(valence_charge)
                    self.pseudized = True
                else:
                    self.error(ion + ' cannot be pseudized', exit=False)
                #end if
            else:
                self.error(ion + ' is not in the physical system', exit=False)
                errors = True
            #end if
        #end for
        if errors:
            self.error('system cannot be generated')
        #end if
        self.valency = obj(**valency)
        self.update()

    #end def pseudize

    def check_folded_system(self, exit=True, message=False):
        msg = ''
        sys_folded = self.folded_system != None
        struct_folded = self.structure.folded_structure != None
        if sys_folded != struct_folded:
            msg += 'folding of physical system and structure is not consistent\nsystem folded: {0}\nstructure folded: {1}\n'.format(
                sys_folded, struct_folded)
        #end if
        if sys_folded and id(self.structure.folded_structure) != id(
                self.folded_system.structure):
            msg += 'structure of folded system and folded structure are distinct\nthis is not allowed and may be a developer error'
        #end if
        success = len(msg) == 0
        if not success and exit:
            self.error(msg)
        #end if
        if not message:
            return success
        else:
            return success, msg
        #end if

    #end def check_folded_system

    def check_consistent(self, tol=1e-8, exit=True, message=False):
        fs, fm = self.check_folded_system(exit=False, message=True)
        cs, cm = self.structure.check_consistent(tol, exit=False, message=True)
        msg = ''
        if not fs:
            msg += fm + '\n'
        #end if
        if not cs:
            msg += cm + '\n'
        #end if
        consistent = len(msg) == 0
        if not consistent and exit:
            self.error(msg)
        #end if
        if not message:
            return consistent
        else:
            return consistent, msg
        #end if

    #end def check_consistent

    def is_valid(self):
        return self.check_consistent(exit=False)

    #end def is_valid

    def change_units(self, units):
        self.structure.change_units(units, folded=False)
        if self.folded_system != None:
            self.folded_system.change_units(units)
        #end if

    #end def change_units

    def group_atoms(self):
        self.structure.group_atoms(folded=False)
        if self.folded_system != None:
            self.folded_system.group_atoms()
        #end if

    #end def group_atoms

    def rename(self, folded=True, **name_pairs):
        self.particles.rename(**name_pairs)
        self.structure.rename(folded=False, **name_pairs)
        if self.pseudized:
            for old, new in name_pairs.items():
                if old in self.valency:
                    if new not in self.valency:
                        self.valency[new] = self.valency[old]
                    #end if
                    del self.valency[old]
                #end if
            #end for
            self.valency_in = self.valency
        #end if
        if self.folded_system != None and folded:
            self.folded_system.rename(folded=folded, **name_pairs)
        #end if

    #end def rename

    def copy(self):
        cp = DevBase.copy(self)
        if self.folded_system != None and self.structure.folded_structure != None:
            del cp.folded_system.structure
            cp.folded_system.structure = cp.structure.folded_structure
        #end if
        return cp

    #end def copy

    def load(self, filepath):
        DevBase.load(self, filepath)
        if self.folded_system != None and self.structure.folded_structure != None:
            del self.folded_system.structure
            self.folded_system.structure = self.structure.folded_structure
        #end if

    #end def load

    def tile(self, *td, **kwargs):
        extensive = True
        net_spin = None
        if 'extensive' in kwargs:
            extensive = kwargs['extensive']
        #end if
        if 'net_spin' in kwargs:
            net_spin = kwargs['net_spin']
        #end if
        supercell = self.structure.tile(*td)
        supercell.remove_folded()
        if extensive:
            ncells = int(round(supercell.volume() / self.structure.volume()))
            net_charge = ncells * self.net_charge
            if net_spin is None:
                net_spin = ncells * self.net_spin
            #end if
        else:
            net_charge = self.net_charge
            if net_spin is None:
                net_spin = self.net_spin
            #end if
        #end if
        system = self.copy()
        supersystem = PhysicalSystem(structure=supercell,
                                     net_charge=net_charge,
                                     net_spin=net_spin,
                                     **self.valency)
        supersystem.folded_system = system
        supersystem.structure.set_folded(system.structure)
        return supersystem

    #end def tile

    def has_folded(self):
        return self.folded_system is not None

    #end def has_folded

    def remove_folded_system(self):
        self.folded_system = None
        self.structure.remove_folded_structure()

    #end def remove_folded_system

    def remove_folded(self):
        self.remove_folded_system()

    #end def remove_folded

    def get_smallest(self):
        if self.has_folded():
            return self.folded_system
        else:
            return self
        #end if

    #end def get_smallest

    def is_magnetic(self):
        return self.net_spin != 0 or self.structure.is_magnetic()

    #end def is_magnetic

    def spin_polarized_orbitals(self):
        return self.is_magnetic()

    #end def spin_polarized_orbitals

    # test needed
    def large_Zeff_elem(self, Zmin):
        elem = []
        for atom, Zeff in self.valency.items():
            if Zeff > Zmin:
                elem.append(atom)
            #end if
        #end for
        return elem

    #end def large_Zeff_elem

    # test needed
    def ae_pp_species(self):
        species = set(self.structure.elem)
        if self.pseudized:
            pp_species = set(self.valency.keys())
            ae_species = species - pp_species
        else:
            pp_species = set()
            ae_species = species
        #end if
        return ae_species, pp_species

    #end def ae_pp_species

    def kf_rpa(self):
        nelecs = self.particles.electron_counts()
        volume = self.structure.volume()
        kvol1 = (2 * np.pi)**3 / volume  # k-space volume per particle
        kfs = [(3 * nelec * kvol1 / (4 * np.pi))**(1. / 3) for nelec in nelecs]
        return np.array(kfs)
示例#2
0
class PhysicalSystem(Matter):

    def __init__(self,structure=None,net_charge=0,net_spin=0,particles=None,**valency):

        self.pseudized = False

        if structure is None:
            self.structure = Structure()
        else:
            self.structure = structure
        #end if
        if particles is None:
            self.particles = Particles()
        else:
            self.particles = particles.copy()
        #end if

        self.folded_system = None
        if self.structure.folded_structure!=None:
            vratio = structure.volume()/structure.folded_structure.volume()
            ncells = int(round(vratio))
            if abs(vratio-ncells)>1e-4:
                self.error('volume of system does not divide evenly into folded system')
            #end if
            if net_charge%ncells!=0:
                self.error('net charge of system does not divide evenly into folded system')
            #end if
            if net_spin%ncells!=0:
                self.error('net_spin of system does not divide evenly into folded system')
            #end if
            self.folded_system = PhysicalSystem(
                structure  = structure.folded_structure,
                net_charge = net_charge/ncells,
                net_spin   = net_spin/ncells,
                particles  = particles,
                **valency
                )
        #end if

        self.valency_in = obj(**valency)
        self.net_charge_in = net_charge
        self.net_spin_in   = net_spin

        self.update_particles(clear=False)

        self.check_folded_system()
    #end def __init__


    def update_particles(self,clear=True):
        #add ions
        pc = dict()
        elem = list(self.structure.elem)
        for ion in set(elem):
            pc[ion] = elem.count(ion)
        #end for
        missing = set(pc.keys())-set(self.particles.keys())
        if len(missing)>0 or len(elem)==0:
            if clear:
                self.particles.clear()
            #end if
            self.add_particles(**pc)

            #pseudize
            if len(self.valency_in)>0:
                self.pseudize(**self.valency_in)
            #end if

            #add electrons
            self.generate_electrons(self.net_charge_in,self.net_spin_in)
        #end if
    #end def update_particles


    def update(self):
        self.net_charge = self.structure.background_charge
        self.net_spin   = 0
        for p in self.particles:
            self.net_charge += p.count*p.charge
            self.net_spin   += p.count*p.spin
        #end for
        self.net_charge = int(round(float(self.net_charge)))
        self.net_spin   = int(round(float(self.net_spin)))
    #end def update


    def add_particles(self,**particle_counts):
        pc = self.particle_collection # all known particles
        plist = []
        for name,count in particle_counts.iteritems():
            particle = pc.get_particle(name)
            if particle is None:
                self.error('particle {0} is unknown'.format(name))
            else:
                particle = particle.copy()
            #end if
            particle.set_count(count)
            plist.append(particle)
        #end for
        self.particles.add_particles(plist)
        self.update()
    #end def add_particles


    def generate_electrons(self,net_charge=0,net_spin=0):
        nelectrons = -net_charge + self.net_charge
        if net_spin=='low':
            net_spin = nelectrons%2
        #end if
        nup   = float(nelectrons + net_spin - self.net_spin)/2
        ndown = float(nelectrons - net_spin + self.net_spin)/2        
        if abs(nup-int(nup))>1e-3:
            self.error('requested spin state {0} incompatible with {1} electrons'.format(net_spin,nelectrons))
        #end if
        nup   = int(nup)
        ndown = int(ndown)
        self.add_particles(up_electron=nup,down_electron=ndown)
    #end def generate_electrons


    def pseudize(self,**valency):
        errors = False
        for ion,valence_charge in valency.iteritems():
            if ion in self.particles:
                ionp = self.particles[ion]
                if isinstance(ionp,Ion):
                    self.particles[ion] = ionp.pseudize(valence_charge)
                    self.pseudized = True
                else:
                    self.error(ion+' cannot be pseudized',exit=False)
                #end if
            else:
                self.error(ion+' is not in the physical system',exit=False)
                errors = True
            #end if
        #end for
        if errors:
            self.error('system cannot be generated')
        #end if
        self.valency = obj(**valency)
        self.update()
    #end def pseudize

        
    def check_folded_system(self):
        sys_folded    = self.folded_system!=None
        struct_folded = self.structure.folded_structure!=None
        if sys_folded!=struct_folded:
            self.error('folding of physical system and structure is not consistent\n  system folded: {0}\n  structure folded: {1}'.format(sys_folded,struct_folded))
        #end if
        if sys_folded and id(self.structure.folded_structure)!=id(self.folded_system.structure):
            self.error('structure of folded system and folded structure are distinct\n  this is not allowed and may be a developer error')
        #end if
    #end def check_folded_system


    def change_units(self,units):
        self.structure.change_units(units,folded=False)
        if self.folded_system!=None:
            self.folded_system.change_units(units)
        #end if
    #end def change_units


    def group_atoms(self):
        self.structure.group_atoms(folded=False)
        if self.folded_system!=None:
            self.folded_system.group_atoms()
        #end if
    #end def group_atoms


    def rename(self,folded=True,**name_pairs):
        self.particles.rename(**name_pairs)
        self.structure.rename(folded=False,**name_pairs)
        if self.folded_system!=None and folded:
            self.folded_system.rename(folded=folded,**name_pairs)
        #end if
    #end def rename


    def copy(self):
        cp = DevBase.copy(self)
        if self.folded_system!=None and self.structure.folded_structure!=None:
            del cp.folded_system.structure
            cp.folded_system.structure = cp.structure.folded_structure
        #end if
        return cp
    #end def copy


    def load(self,filepath):
        DevBase.load(self,filepath)
        if self.folded_system!=None and self.structure.folded_structure!=None:
            del self.folded_system.structure
            self.folded_system.structure = self.structure.folded_structure
        #end if
    #end def load


    def tile(self,*td,**kwargs):
        extensive = True
        net_spin  = None
        if 'extensive' in kwargs:
            extensive = kwargs['extensive']
        #end if
        if 'net_spin' in kwargs:
            net_spin = kwargs['net_spin']
        #end if
        supercell = self.structure.tile(*td)
        supercell.remove_folded()
        if extensive:
            ncells = int(round(supercell.volume()/self.structure.volume()))
            net_charge = ncells*self.net_charge
            if net_spin is None:
                net_spin   = ncells*self.net_spin
            #end if
        else:
            net_charge = self.net_charge
            if net_spin is None:
                net_spin   = self.net_spin
            #end if
        #end if
        system = self.copy()
        supersystem = PhysicalSystem(
            structure  = supercell,
            net_charge = net_charge,
            net_spin   = net_spin,
            **self.valency
            )
        supersystem.folded_system = system
        supersystem.structure.set_folded(system.structure)
        return supersystem
    #end def tile


    def remove_folded_system(self):
        self.folded_system = None
        self.structure.remove_folded_structure()
    #end def remove_folded_system


    def get_primitive(self):
        if self.folded_system is None:
            fs = self
        else:
            fs = self.folded_system
            while fs.folded_system!=None:
                fs = fs.folded_system
            #end while
        #end if
        return fs
    #end def get_primitive


    def folded_representation(self,arg0,arg1=None):
        self.error('folded_representation needs a developers attention to make it equivalent with tile')
        if isinstance(arg0,PhysicalSystem):
            folded_system = arg0
        elif isinstance(arg0,str):
            shape = arg0
            tiling    = arg1
            if tiling is None:
                tiling = (1,1,1)
            #end if
            if not 'generation_info' in self:
                self.error('system was not formed with generate_physical_system, cannot form folded representation')
            #end if
            structure,element,scale,units,net_charge,net_spin,particles,valency = \
                self.generation_info.tuple('structure','element','scale','units', \
                                               'net_charge','net_spin','particles','valency')
            folded_system = generate_physical_system(
                structure  = structure,
                shape      = shape,
                element    = element,
                tiling     = tiling,
                scale      = scale,
                units      = units,
                net_charge = net_charge,
                net_spin   = net_spin,
                particles  = particles,
                **valency
                )
        else:
            self.error('unrecognized inputs in folded_representation')
        #end if
        tilematrix,kmap = self.structure.fold(folded_system.structure,'tilematrix','kmap')
        self.set(
            folded_system = folded_system,
            tilematrix    = tilematrix,
            kmap          = kmap
            )
        return folded_system
    #end def folded_representation


    def large_Zeff_elem(self,Zmin):
        elem = []
        for atom,Zeff in self.valency.iteritems():
            if Zeff>Zmin:
                elem.append(atom)
            #end if
        #end for
        return elem
示例#3
0
class PhysicalSystem(Matter):

    def __init__(self,structure=None,net_charge=0,net_spin=0,particles=None,**valency):

        self.pseudized = False

        if structure is None:
            self.structure = Structure()
        else:
            self.structure = structure
        #end if
        if particles is None:
            self.particles = Particles()
        else:
            self.particles = particles.copy()
        #end if

        self.folded_system = None
        if self.structure.folded_structure!=None:
            vratio = structure.volume()/structure.folded_structure.volume()
            ncells = int(round(vratio))
            if abs(vratio-ncells)>1e-4:
                self.error('volume of system does not divide evenly into folded system')
            #end if
            if net_charge%ncells!=0:
                self.error('net charge of system does not divide evenly into folded system')
            #end if
            if net_spin%ncells!=0:
                self.error('net_spin of system does not divide evenly into folded system')
            #end if
            self.folded_system = PhysicalSystem(
                structure  = structure.folded_structure,
                net_charge = net_charge/ncells,
                net_spin   = net_spin/ncells,
                particles  = particles,
                **valency
                )
        #end if

        self.valency_in = obj(**valency)
        self.net_charge_in = net_charge
        self.net_spin_in   = net_spin

        self.update_particles(clear=False)

        self.check_folded_system()
    #end def __init__


    def update_particles(self,clear=True):
        #add ions
        pc = dict()
        elem = list(self.structure.elem)
        for ion in set(elem):
            pc[ion] = elem.count(ion)
        #end for
        missing = set(pc.keys())-set(self.particles.keys())
        if len(missing)>0 or len(elem)==0:
            if clear:
                self.particles.clear()
            #end if
            self.add_particles(**pc)

            #pseudize
            if len(self.valency_in)>0:
                self.pseudize(**self.valency_in)
            #end if

            #add electrons
            self.generate_electrons(self.net_charge_in,self.net_spin_in)
        #end if
    #end def update_particles


    def update(self):
        self.net_charge = self.structure.background_charge
        self.net_spin   = 0
        for p in self.particles:
            self.net_charge += p.count*p.charge
            self.net_spin   += p.count*p.spin
        #end for
        self.net_charge = int(round(float(self.net_charge)))
        self.net_spin   = int(round(float(self.net_spin)))
    #end def update


    def add_particles(self,**particle_counts):
        pc = self.particle_collection # all known particles
        plist = []
        for name,count in particle_counts.iteritems():
            particle = pc.get_particle(name)
            if particle is None:
                self.error('particle {0} is unknown'.format(name))
            else:
                particle = particle.copy()
            #end if
            particle.set_count(count)
            plist.append(particle)
        #end for
        self.particles.add_particles(plist)
        self.update()
    #end def add_particles


    def generate_electrons(self,net_charge=0,net_spin=0):
        nelectrons = -net_charge + self.net_charge
        if net_spin=='low':
            net_spin = nelectrons%2
        #end if
        nup   = float(nelectrons + net_spin - self.net_spin)/2
        ndown = float(nelectrons - net_spin + self.net_spin)/2        
        if abs(nup-int(nup))>1e-3:
            self.error('requested spin state {0} incompatible with {1} electrons'.format(net_spin,nelectrons))
        #end if
        nup   = int(nup)
        ndown = int(ndown)
        self.add_particles(up_electron=nup,down_electron=ndown)
    #end def generate_electrons


    def pseudize(self,**valency):
        errors = False
        for ion,valence_charge in valency.iteritems():
            if ion in self.particles:
                ionp = self.particles[ion]
                if isinstance(ionp,Ion):
                    self.particles[ion] = ionp.pseudize(valence_charge)
                    self.pseudized = True
                else:
                    self.error(ion+' cannot be pseudized',exit=False)
                #end if
            else:
                self.error(ion+' is not in the physical system',exit=False)
                errors = True
            #end if
        #end for
        if errors:
            self.error('system cannot be generated')
        #end if
        self.valency = obj(**valency)
        self.update()
    #end def pseudize

        
    def check_folded_system(self):
        sys_folded    = self.folded_system!=None
        struct_folded = self.structure.folded_structure!=None
        if sys_folded!=struct_folded:
            self.error('folding of physical system and structure is not consistent\n  system folded: {0}\n  structure folded: {1}'.format(sys_folded,struct_folded))
        #end if
        if sys_folded and id(self.structure.folded_structure)!=id(self.folded_system.structure):
            self.error('structure of folded system and folded structure are distinct\n  this is not allowed and may be a developer error')
        #end if
    #end def check_folded_system


    def change_units(self,units):
        self.structure.change_units(units,folded=False)
        if self.folded_system!=None:
            self.folded_system.change_units(units)
        #end if
    #end def change_units


    def group_atoms(self):
        self.structure.group_atoms(folded=False)
        if self.folded_system!=None:
            self.folded_system.group_atoms()
        #end if
    #end def group_atoms


    def rename(self,folded=True,**name_pairs):
        self.particles.rename(**name_pairs)
        self.structure.rename(folded=False,**name_pairs)
        if self.pseudized:
            for old,new in name_pairs.iteritems():
                if old in self.valency:
                    if new not in self.valency:
                        self.valency[new] = self.valency[old]
                    #end if
                    del self.valency[old]
                #end if
            #end for
            self.valency_in = self.valency
        #end if
        if self.folded_system!=None and folded:
            self.folded_system.rename(folded=folded,**name_pairs)
        #end if
    #end def rename


    def copy(self):
        cp = DevBase.copy(self)
        if self.folded_system!=None and self.structure.folded_structure!=None:
            del cp.folded_system.structure
            cp.folded_system.structure = cp.structure.folded_structure
        #end if
        return cp
    #end def copy


    def load(self,filepath):
        DevBase.load(self,filepath)
        if self.folded_system!=None and self.structure.folded_structure!=None:
            del self.folded_system.structure
            self.folded_system.structure = self.structure.folded_structure
        #end if
    #end def load


    def tile(self,*td,**kwargs):
        extensive = True
        net_spin  = None
        if 'extensive' in kwargs:
            extensive = kwargs['extensive']
        #end if
        if 'net_spin' in kwargs:
            net_spin = kwargs['net_spin']
        #end if
        supercell = self.structure.tile(*td)
        supercell.remove_folded()
        if extensive:
            ncells = int(round(supercell.volume()/self.structure.volume()))
            net_charge = ncells*self.net_charge
            if net_spin is None:
                net_spin   = ncells*self.net_spin
            #end if
        else:
            net_charge = self.net_charge
            if net_spin is None:
                net_spin   = self.net_spin
            #end if
        #end if
        system = self.copy()
        supersystem = PhysicalSystem(
            structure  = supercell,
            net_charge = net_charge,
            net_spin   = net_spin,
            **self.valency
            )
        supersystem.folded_system = system
        supersystem.structure.set_folded(system.structure)
        return supersystem
    #end def tile


    def remove_folded_system(self):
        self.folded_system = None
        self.structure.remove_folded_structure()
    #end def remove_folded_system


    def remove_folded(self):
        self.remove_folded_system()
    #end def remove_folded


    def get_primitive(self):
        if self.folded_system is None:
            fs = self
        else:
            fs = self.folded_system
            while fs.folded_system!=None:
                fs = fs.folded_system
            #end while
        #end if
        return fs
    #end def get_primitive


    def folded_representation(self,arg0,arg1=None):
        self.error('folded_representation needs a developers attention to make it equivalent with tile')
        if isinstance(arg0,PhysicalSystem):
            folded_system = arg0
        elif isinstance(arg0,str):
            shape = arg0
            tiling    = arg1
            if tiling is None:
                tiling = (1,1,1)
            #end if
            if not 'generation_info' in self:
                self.error('system was not formed with generate_physical_system, cannot form folded representation')
            #end if
            structure,element,scale,units,net_charge,net_spin,particles,valency = \
                self.generation_info.tuple('structure','element','scale','units', \
                                               'net_charge','net_spin','particles','valency')
            folded_system = generate_physical_system(
                structure  = structure,
                shape      = shape,
                element    = element,
                tiling     = tiling,
                scale      = scale,
                units      = units,
                net_charge = net_charge,
                net_spin   = net_spin,
                particles  = particles,
                **valency
                )
        else:
            self.error('unrecognized inputs in folded_representation')
        #end if
        tilematrix,kmap = self.structure.fold(folded_system.structure,'tilematrix','kmap')
        self.set(
            folded_system = folded_system,
            tilematrix    = tilematrix,
            kmap          = kmap
            )
        return folded_system
    #end def folded_representation


    def large_Zeff_elem(self,Zmin):
        elem = []
        for atom,Zeff in self.valency.iteritems():
            if Zeff>Zmin:
                elem.append(atom)
            #end if
        #end for
        return elem
    #end def large_Zeff_elem


    def ae_pp_species(self):
        species = set(self.structure.elem)
        if self.pseudized:
            pp_species = set(self.valency.keys())
            ae_species = species-pp_species
        else:
            pp_species = set()
            ae_species = species
        #end if
        return ae_species,pp_species
示例#4
0
class PhysicalSystem(Matter):

    def __init__(self,structure=None,net_charge=0,net_spin=0,particles=None,**valency):

        self.structure = structure
        self.particles = particles
        if structure==None:
            self.structure = Structure()
        #end if
        if particles==None:
            self.particles = Particles()
        #end if

        self.folded_system = None
        if self.structure.folded_structure!=None:
            self.folded_system = PhysicalSystem(
                structure  = structure.folded_structure,
                net_charge = net_charge,
                net_spin   = net_spin,
                particles  = particles,
                **valency
                )
        #end if

        #add ions
        pc = dict()
        elem = list(self.structure.elem)
        for ion in set(elem):
            pc[ion] = elem.count(ion)
        #end for
        self.add_particles(**pc)

        #pseudize
        if len(valency)>0:
            self.pseudize(**valency)
        #end if

        #add electrons
        self.generate_electrons(net_charge,net_spin)

        self.check_folded_system()
    #end def __init__


    def update(self):
        self.net_charge = 0
        self.net_spin   = 0
        for p in self.particles:
            self.net_charge += p.count*p.charge
            self.net_spin   += p.count*p.spin
        #end for
        self.net_charge = int(round(float(self.net_charge)))
        self.net_spin = int(round(float(self.net_spin)))
    #end def update


    def add_particles(self,**particle_counts):
        plist = []
        for name,count in particle_counts.iteritems():
            particle = self.particle_collection[name].copy()
            particle.set_count(count)
            plist.append(particle)
        #end for
        self.particles.add_particles(plist)
        self.update()
    #end def add_particles


    def generate_electrons(self,net_charge=0,net_spin=0):
        nelectrons = -net_charge + self.net_charge
        if net_spin=='low':
            net_spin = nelectrons%2
        #end if
        nup   = float(nelectrons + net_spin - self.net_spin)/2
        ndown = float(nelectrons - net_spin + self.net_spin)/2        
        if abs(nup-int(nup))>1e-3:
            self.error('requested spin state {0} incompatible with {1} electrons'.format(net_spin,nelectrons))
        #end if
        nup   = int(nup)
        ndown = int(ndown)
        self.add_particles(up_electron=nup,down_electron=ndown)
    #end def generate_electrons


    def pseudize(self,**valency):
        errors = False
        for ion,valence_charge in valency.iteritems():
            if ion in self.particles:
                ionp = self.particles[ion]
                if isinstance(ionp,Ion):
                    self.particles[ion] = ionp.pseudize(valence_charge)
                else:
                    self.error(ion+' cannot be pseudized',exit=False)
                #end if
            else:
                self.error(ion+' is not in the physical system',exit=False)
                errors = True
            #end if
        #end for
        if errors:
            self.error('system cannot be generated')
        #end if
        self.valency = obj(**valency)
        self.update()
    #end def pseudize

        
    def check_folded_system(self):
        sys_folded    = self.folded_system!=None
        struct_folded = self.structure.folded_structure!=None
        if sys_folded!=struct_folded:
            self.error('folding of physical system and structure is not consistent\n  system folded: {0}\n  structure folded: {1}'.format(sys_folded,struct_folded))
        #end if
        if sys_folded and id(self.structure.folded_structure)!=id(self.folded_system.structure):
            self.error('structure of folded system and folded structure are distinct\n  this is not allowed and may be a developer error')
        #end if
    #end def check_folded_system


    def change_units(self,units):
        self.structure.change_units(units)
        if self.folded_system!=None:
            self.folded_system.change_units(units)
        #end if
    #end def change_units


    def group_atoms(self):
        self.structure.group_atoms()
        if self.folded_system!=None:
            self.folded_system.group_atoms()
        #end if
    #end def group_atoms


    def copy(self):
        cp = DevBase.copy(self)
        if self.folded_system!=None and self.structure.folded_structure!=None:
            del cp.folded_system.structure
            cp.folded_system.structure = cp.structure.folded_structure
        #end if
        return cp
    #end def copy


    def load(self,filepath):
        DevBase.load(self,filepath)
        if self.folded_system!=None and self.structure.folded_structure!=None:
            del self.folded_system.structure
            self.folded_system.structure = self.structure.folded_structure
        #end if
    #end def load


    def tile(self,*td,**kwargs):
        extensive = True
        if 'extensive' in kwargs:
            extensive = kwargs['extensive']
        #end if
        supercell = self.structure.tile(*td)
        if extensive:
            ncells = int(round(supercell.volume()/self.structure.volume()))
            net_charge = ncells*self.net_charge
            net_spin   = ncells*self.net_spin
        else:
            net_charge = self.net_charge
            net_spin   = self.net_spin
        #end if
        supersystem = PhysicalSystem(
            structure  = supercell,
            net_charge = net_charge,
            net_spin   = net_spin,
            **self.valency
            )
        return supersystem
    #end def tile


    def remove_folded_system(self):
        print 'removing folded system',self.folded_system.__class__.__name__
        self.folded_system = None
        self.structure.remove_folded_structure()
    #end def remove_folded_system


    def folded_representation(self,arg0,arg1=None):
        self.error('folded_representation needs a developers attention to make it equivalent with tile')
        if isinstance(arg0,PhysicalSystem):
            folded_system = arg0
        elif isinstance(arg0,str):
            shape = arg0
            tiling    = arg1
            if tiling is None:
                tiling = (1,1,1)
            #end if
            if not 'generation_info' in self:
                self.error('system was not formed with generate_physical_system, cannot form folded representation')
            #end if
            structure,element,scale,units,net_charge,net_spin,particles,valency = \
                self.generation_info.tuple('structure','element','scale','units', \
                                               'net_charge','net_spin','particles','valency')
            folded_system = generate_physical_system(
                structure  = structure,
                shape      = shape,
                element    = element,
                tiling     = tiling,
                scale      = scale,
                units      = units,
                net_charge = net_charge,
                net_spin   = net_spin,
                particles  = particles,
                **valency
                )
        else:
            self.error('unrecognized inputs in folded_representation')
        #end if
        tilematrix,kmap = self.structure.fold(folded_system.structure,'tilematrix','kmap')
        self.set(
            folded_system = folded_system,
            tilematrix    = tilematrix,
            kmap          = kmap
            )
        return folded_system