コード例 #1
0
 def ParseZmatSection(self, line):
     """Parse the geometry (XYZ only for the moment)."""
     # . Get the terminator as the opening character of the current line.
     terminator = line[0:1]
     # . Initialization.
     atomicNumbers = []
     xyz = []
     nwarnings0 = self.nwarnings
     # . Loop until an end of section is reached.
     while True:
         items = self.GetTokens(converters=[
             None, JaguarInputFileReader.ToFloat,
             JaguarInputFileReader.ToFloat, JaguarInputFileReader.ToFloat
         ])
         # . The end found.
         if (len(items) == 1) and (items[0] == terminator):
             break
         # . An XYZ line.
         elif len(items) == 4:
             atomicNumber = PeriodicTable.AtomicNumber(items[0])
             if atomicNumber > 0:
                 atomicNumbers.append(atomicNumber)
                 xyz.append((items[1], items[2], items[3]))
         # . Other lines.
         else:
             self.Warning("Unable to interpret geometry line.", True)
     # . Save the data if there have been no warnings.
     if nwarnings0 == self.nwarnings:
         self.atomicNumbers = atomicNumbers
         self.coordinates3 = Coordinates3.WithExtent(len(xyz))
         for (i, (x, y, z)) in enumerate(xyz):
             self.coordinates3[i, 0] = x
             self.coordinates3[i, 1] = y
             self.coordinates3[i, 2] = z
コード例 #2
0
 def ParseGeometry(self):
     """Parse a geometry."""
     self.GetLine()  # .The Angstroms line.
     self.GetLine()  # . The atoms heading.
     atomicNumbers = []
     xyz = []
     dummies = set()
     n = 0
     while True:
         tokens = self.GetTokens()
         if (len(tokens) == 4):
             atomicNumber = PeriodicTable.AtomicNumber(tokens[0])
             if (atomicNumber > 0):
                 atomicNumbers.append(atomicNumber)
                 x = float(tokens[1])
                 y = float(tokens[2])
                 z = float(tokens[3])
                 xyz.append((x, y, z))
             else:
                 dummies.add(n)
             n += 1
         else:
             break
     if (len(atomicNumbers) > 0):
         self.atomicNumbers = atomicNumbers
         if self.coordinates3 is None:
             self.coordinates3 = Coordinates3.WithExtent(len(xyz))
         for (i, (x, y, z)) in enumerate(xyz):
             self.coordinates3[i, 0] = x
             self.coordinates3[i, 1] = y
             self.coordinates3[i, 2] = z
         self.natoms = len(self.atomicNumbers)
         self.ngeometries += 1
         self.dummies = dummies
コード例 #3
0
 def ParseAtomSection(self):
     """Parse the ATOM section."""
     if hasattr(self, "natoms"):
         atomicCharges = Real1DArray.WithExtent(self.natoms)
         atomicCharges.Set(0.0)
         atomicNumbers = []
         atomNames = []
         xyz = Coordinates3.WithExtent(self.natoms)
         xyz.Set(0.0)
         for i in range(self.natoms):
             items = self.GetTokens(converters=[
                 int, None, float, float, float, None, None, None, float
             ])
             if len(items) < 6:
                 self.Warning("Invalid ATOM line.", True)
             else:
                 atomicNumber = PeriodicTable.AtomicNumber(items[1])
                 if atomicNumber <= 0:
                     atomicNumber = self.AtomicNumberFromAtomType(items[5])
                 atomicNumbers.append(atomicNumber)
                 atomNames.append(items[1])
                 xyz[i, 0] = items[2]
                 xyz[i, 1] = items[3]
                 xyz[i, 2] = items[4]
                 if len(items) >= 9: atomicCharges[i] = items[8]
         self.atomicCharges = atomicCharges
         self.atomicNumbers = atomicNumbers
         self.atomNames = atomNames
         self.xyz = xyz
     else:
         self.Warning("Unknown number of atoms in molecule.", True)
コード例 #4
0
    def Parse(self, log=logFile):
        """Parsing."""
        if not self.QPARSED:
            # . Initialization.
            if LogFileActive(log): self.log = log
            # . Get the atom line format.
            atomlineformat = self.GetAtomLineFormat()
            # . Open the file.
            self.Open()
            # . Parse all the lines.
            try:
                # . Keyword line.
                self.title = self.GetLine()
                # . Number of atoms.
                items = self.GetTokens(converters=(int, ))
                natoms = items[0]
                # . The coordinate data.
                self.xyz = Coordinates3(natoms)
                for n in range(natoms):
                    tokens = self.GetFixedFormatTokens(*atomlineformat)
                    for i in range(3):
                        self.xyz[n, i] = float(tokens[i + 3] * 10.0)
                # . Symmetry data.
                self.symmetryItems = self.GetTokens()
            except EOFError:
                pass
# . Close the file.
            self.WarningStop()
            self.Close()
            # . Set the parsed flag and some other options.
            self.log = None
            self.QPARSED = True
コード例 #5
0
    def Parse(self, log=logFile):
        """Parse the data on the file."""
        if not self.QPARSED:
            # . Initialization.
            if LogFileActive(log): self.log = log
            # . Open the file.
            self.Open()
            try:
                # . Number of atoms.
                items = self.GetTokens(converters=[int])
                natoms = items[0]
                # . Title line.
                self.title = self.GetLine()
                # . XYZ lines.
                self.atomicNumbers = []
                self.coordinates3 = Coordinates3.WithExtent(natoms)
                for i in range(natoms):
                    items = self.GetTokens(converters=[
                        PeriodicTable.AtomicNumber, float, float, float
                    ])
                    self.atomicNumbers.append(items[0])
                    self.coordinates3[i, 0] = items[1]
                    self.coordinates3[i, 1] = items[2]
                    self.coordinates3[i, 2] = items[3]
            except EOFError:
                pass
# . Close the file.
            self.WarningStop()
            self.Close()
            # . Set the parsed flag and some other options.
            self.log = None
            self.QPARSED = True
コード例 #6
0
def NormalModesTrajectory_SystemGeometry(system,
                                         trajectory,
                                         cycles=10,
                                         frames=21,
                                         mode=0,
                                         state=None,
                                         temperature=300.0):
    """Generate a normal mode trajectory."""

    # . Get the state.
    if state is None: state = system.configuration.nmState

    # . Get state-related information.
    if state.freeAtoms == None: freeAtoms = range(len(system.atoms))
    else: freeAtoms = state.freeAtoms
    frequencies = state.frequencies
    modes = state.modes

    # . Get the mode frequency.
    omega = math.fabs(frequencies[mode])

    # . Calculate the number of frames.
    total = cycles * frames

    # . Check for a calculation.
    if (mode >= 0) and (mode < state.dimension) and (
            omega > _LOWFREQUENCY) and (total > 0):

        # . Calculate the amplitude (in Angstroms).
        amplitude = math.sqrt(
            2.0 * 1.0e-3 * CONSTANT_AVOGADRO_NUMBER * CONSTANT_BOLTZMANN *
            temperature) * (_TO_WAVENUMBERS / omega)

        # . Allocate space for the coordinates and mode.
        coordinates3 = Clone(system.coordinates3)
        displacement = Coordinates3.WithExtent(len(system.atoms))
        displacement.Set(0.0)

        # . Get the displacement.
        for f in freeAtoms:
            displacement[f, 0] = modes[mode, 3 * f]
            displacement[f, 1] = modes[mode, 3 * f + 1]
            displacement[f, 2] = modes[mode, 3 * f + 2]

        # . Loop over the cycles and frames.
        # . Calculate the displacement prefactor using sine instead of cosine.
        trajectory.WriteHeader(temperature=temperature)
        for c in range(cycles):
            for f in range(frames):
                factor = amplitude * math.sin(
                    2.0 * math.pi * float(f) / float(frames))
                coordinates3.CopyTo(system.coordinates3)
                system.coordinates3.AddScaledMatrix(factor, displacement)
                trajectory.WriteOwnerData()

        # . Finish up.
        trajectory.WriteFooter()
        trajectory.Close()
コード例 #7
0
    def Setup ( selfClass, qcAtoms, electronicState, nbState, job, scratch, deleteJobFiles = False, useRandomJob = False, useRandomScratch = False ):
        """Set up a state given the relevant data."""
        self = selfClass ( )
        # . QC atoms.
        # . Basic attributes.
        self.charge          = electronicState.charge
        self.multiplicity    = electronicState.multiplicity
        self.numberOfQCAtoms = len ( qcAtoms )
        # . File paths.
        if useRandomJob: job = RandomString ( )
        if useRandomScratch:
            self.scratchPath = os.path.join ( scratch, RandomString ( ) )
            if not os.path.exists ( self.scratchPath ): os.mkdir ( self.scratchPath )
            self.jobPath     = os.path.join ( self.scratchPath, job )
        else:
            self.scratchPath = None
            self.jobPath     = os.path.join ( scratch, job )
        self.engradPath = self.jobPath + ".engrad"
        self.inputPath  = self.jobPath + ".inp"
        self.outputPath = self.jobPath + ".log"
	self.pcgradPath = self.jobPath + ".pcgrad"
	self.pcPath     = self.jobPath + ".pc"
        # . Options.
        self.deleteJobFiles = deleteJobFiles
        # . Symbols.
        atomicNumbers = qcAtoms.GetAtomicNumbers ( )
        self.symbols  = []
        for i in atomicNumbers:
            self.symbols.append ( PeriodicTable.Symbol ( i ) )
        # . Array attributes.
        self.qcCoordinates3  = Coordinates3.WithExtent ( self.numberOfQCAtoms ) ; self.qcCoordinates3.Set  ( 0.0 )
        self.dipole          = Vector3.Null ( )
        self.qcGradients3    = Coordinates3.WithExtent ( self.numberOfQCAtoms ) ; self.qcGradients3.Set    ( 0.0 )
        self.chelpgCharges   = Real1DArray.WithExtent  ( self.numberOfQCAtoms ) ; self.chelpgCharges.Set   ( 0.0 )
        self.lowdinCharges   = Real1DArray.WithExtent  ( self.numberOfQCAtoms ) ; self.lowdinCharges.Set   ( 0.0 )
        self.lowdinSpins     = Real1DArray.WithExtent  ( self.numberOfQCAtoms ) ; self.lowdinSpins.Set     ( 0.0 )
        self.mullikenCharges = Real1DArray.WithExtent  ( self.numberOfQCAtoms ) ; self.mullikenCharges.Set ( 0.0 )
        self.mullikenSpins   = Real1DArray.WithExtent  ( self.numberOfQCAtoms ) ; self.mullikenSpins.Set   ( 0.0 )
        # . Orbital data.
        self.H**O            = -1
        self.LUMO            = -1
        self.orbitalEnergies = []
        # . NB state.
        self.nbState = nbState
        return self
コード例 #8
0
 def IncludeSymmetryParameters ( self ):
     """Flag the symmetry parameters as variables."""
     if ( self.system.symmetry is not None ) and ( self.system.symmetry.crystalClass is not None ):
         nvariables = len ( self.system.symmetry.crystalClass )
         if nvariables > 0:
             self.fractional         = Coordinates3.WithExtent ( self.ncoordinatevariables // 3 )
             self.nsymmetryvariables = nvariables
             self.nvariables        += nvariables
             self.QSYMMETRY          = True
コード例 #9
0
 def ToCoordinates3 ( self ):
     """Return the coordinates."""
     if self.QPARSED:
         coordinates3 = Coordinates3.WithExtent ( len ( self.atoms ) )
         for ( i, datum ) in enumerate ( self.atoms ):
             coordinates3[i,0] = datum[4]
             coordinates3[i,1] = datum[5]
             coordinates3[i,2] = datum[6]
         return coordinates3
     else:
         return None
コード例 #10
0
 def ToCoordinates3(self):
     """Return the coordinates."""
     if self.QPARSED:
         coordinates3 = Coordinates3.WithExtent(len(self.atoms))
         for (i, (aname, atomicNumber, x, y, z)) in enumerate(self.atoms):
             coordinates3[i, 0] = x
             coordinates3[i, 1] = y
             coordinates3[i, 2] = z
         return coordinates3
     else:
         return None
コード例 #11
0
 def VerifyFixedAtomCoordinates(self,
                                trial,
                                log=logFile,
                                reference=None,
                                tolerance=1.0e-03):
     """Verify that the coordinates of fixed atoms in a trial set are the same as in a reference set."""
     # . Initialization.
     fixedAtoms = None
     isOK = False
     if self.hardConstraints is not None:
         fixedAtoms = self.hardConstraints.fixedAtoms
     if reference is None: reference = self.coordinates3
     # . Basic checks.
     if reference is None: message = "Missing reference coordinate set."
     elif trial is None: message = "Missing trial coordinate set."
     elif (trail.rows != len(system.atoms)) or (len(reference) !=
                                                len(trial)):
         message = "Coordinate sets of incompatible size."
     elif fixedAtoms is None:
         isOK = True
         message = "No fixed atoms are defined."
     # . Check the coordinates.
     else:
         set1 = Coordinates3(len(fixedAtoms))
         set1.Gather(reference, fixedAtoms)
         set2 = Coordinates3(len(fixedAtoms))
         set2.Gather(other, fixedAtoms)
         set1.AddScaledMatrix(-1.0, set2)
         biggest = set1.AbsoluteMaximum()
         if biggest >= tolerance:
             message = "The maximum difference in the fixed atom coordinates, {:.6g}, is greater than the tolerance, {:.6g}.".format(
                 biggest, tolerance)
         else:
             isOK = True
             message = "The fixed atom coordinates are compatible."
     # . Printing.
     if LogFileActive(log): log.Paragraph(message)
     # . Finish up.
     return isOK
コード例 #12
0
 def FilterAtoms ( self, filterlevel ):
     """Filter out Mopac-specific atoms."""
     if self.QPARSED and ( filterlevel > -3 ):
         atomicNumbers = []
         selected      = []
         for ( i, a ) in enumerate ( self.atomicNumbers ):
             if a >= filterlevel:
                 atomicNumbers.append ( a )
                 selected.append      ( i )
         if len ( atomicNumbers ) < len ( self.atomicNumbers ):
             coordinates3 = Coordinates3.WithExtent ( len ( atomicNumbers ) )
             coordinates3.Gather ( self.coordinates3, Selection.FromIterable ( selected ) )
             self.atomicNumbers = atomicNumbers
             self.coordinates3  = coordinates3
コード例 #13
0
 def GetGridPointCoordinates ( self ):
     """Return the grid point coordinates."""
     if self.coordinates3 is None:
         coordinates3 = Coordinates3.WithExtent ( self.NumberOfPoints ( ) )
         n = 0
         for ix in range ( self.npoints[0] ):
             for iy in range ( self.npoints[1] ) :
                 for iz in range ( self.npoints[2] ) :
                     point = self.Point ( ix, iy, iz )
                     coordinates3[n,0] = point[0]
                     coordinates3[n,1] = point[1]
                     coordinates3[n,2] = point[2]
                     n += 1
         self.coordinates3 = coordinates3
     return self.coordinates3
コード例 #14
0
 def ToCoordinates3(self, frameIndex=-1):
     """Return a coordinates3 object."""
     coordinates3 = None
     if self.QPARSED:
         frame = self.frames[frameIndex]
         xyz = frame.GetItem("XYZ")
         if xyz is not None:
             coordinates3 = Coordinates3.WithExtent(len(xyz))
             for (i, (x, y, z)) in enumerate(xyz):
                 coordinates3[i, 0] = x
                 coordinates3[i, 1] = y
                 coordinates3[i, 2] = z
             frame.SetItem("Coordinates3", coordinates3)
         else:
             coordinates3 = frame.GetItem("Coordinates3")
     return coordinates3
コード例 #15
0
 def ExtractCoordinates ( self, table, tag ):
     """Extract coordinates from a table."""
     x = table.RealColumnValues ( tag + "_x" )
     y = table.RealColumnValues ( tag + "_y" )
     z = table.RealColumnValues ( tag + "_z" )
     if ( x is not None ) and ( y is not None ) and ( z is not None ):
         xyz = Coordinates3.WithExtent ( len ( x ) )
         for ( i, ( u, v, w ) ) in enumerate ( zip ( x, y, z ) ):
             if ( u is None ) or ( v is None ) or ( w is None ):
                 xyz.FlagCoordinateAsUndefined ( i )
             else:
                 xyz[i,0] = u
                 xyz[i,1] = v
                 xyz[i,2] = w
     else: xyz = None
     return xyz
    def DefineQCLayer ( self, selection, qcModel, electronicState = None ):
        """Define a QC layer.

        A layer consists of two subsystems with the same atomic composition. One uses the new energy model and a weight of +1 whereas the second has the old energy model and a weight of -1.
        """
        # . Get the latest defined system.
        if len ( self.subsystems ) > 0:
            number    = len ( self.subsystems )
            oldsystem = self.subsystems[-1].system
        else:
            number    = 0
            oldsystem = self.system
        # . Get the QC atom indices of the full system (excluding boundary atoms).
        try:    oldqcset = set ( oldsystem.energyModel.qcAtoms.GetFullSelection ( ) ).difference ( set ( oldsystem.energyModel.qcAtoms.BoundaryAtomSelection ( ) ) )
        except: raise ValueError ( "Unable to retrieve the previous system's QC atom indices." )
        # . Map a subsystem's indices to those of the full system.
        if len ( self.subsystems ) > 0:
            mapping  = self.subsystems[-1].selection
            unmapped = oldqcset
            oldqcset = set ( )
            for i in unmapped: oldqcset.add ( mapping[i] )
        # . Check that the selection is a subset of the previous one.
        newqcset = set ( selection )
        if not newqcset.issubset ( oldqcset ): raise ValueError ( "The atoms in the new QC layer must be a subset of the QC atoms in the underlying system." )
        # . Get the old QC model (which at this stage is known to exist).
        oldmodel = oldsystem.energyModel.qcModel
        # . Find the atomic numbers.
        atomicNumbers = self.system.atoms.GetItemAttributes ( "atomicNumber", selection = selection )
        # . Find boundary atoms.
        boundaryAtoms = self.FindBoundaryAtoms ( selection, len ( atomicNumbers ) )
        # . Extend atomicNumbers by the appropriate number of boundary atom hydrogens.
        atomicNumbers.extend ( len ( boundaryAtoms ) * [ 1 ] )
        # . Define a basic QC system - it is cleaner to do this for a QC system from scratch without pruning, etc.
        system0 = System.FromAtoms ( atomicNumbers )
        if electronicState is not None: system0.electronicState = electronicState
        system0.coordinates3 = Coordinates3.WithExtent ( len ( system0.atoms ) )
        system0.coordinates3.Set ( 0.0 )
        # . Define the subsystems of the layer.
        system1 = Clone ( system0 )
        for ( i, ( system, model, weight ) ) in enumerate ( ( ( system0, oldmodel, -1.0 ), ( system1, qcModel, 1.0 ) ) ):
            system.label = "MultiLayer Objective Function Subsystem {:d} with Weight {:.1f}".format ( number+i, weight )
            system.DefineQCModel ( model )
            subsystem = MultiLayerSubsystem ( system, weight, selection, boundaryAtoms = boundaryAtoms )
            subsystem.VariablesPut ( self.system.coordinates3 )
            self.subsystems.append ( subsystem )
コード例 #17
0
    def LinearlyExpand(self, ninsert):
        """Expand a trajectory by inserting points determined by linear interpolation.

        |ninsert| is the number of points to insert between each pair of existing points.
        """
        if not self.isWritable:
            raise IOError("Writing to trajectory that is not writeable.")
        if (ninsert > 0) and (self.frames > 1):
            # . Check for fixed atoms and get the first frame if necessary.
            hasFixedAtoms = (self.owner.hardConstraints is not None) and (
                self.owner.hardConstraints.NumberOfFixedAtoms() > 0)
            if not hasFixedAtoms:
                reference = self.ReadFrame(frame=0, instance=Coordinates3)
            # . Calculate the number of new frames.
            nold = self.frames
            nnew = nold + (nold - 1) * ninsert
            # . Get space for the step.
            dxyz = Coordinates3.WithExtent(len(self.owner.atoms))
            dxyz.Set(0.0)
            # . Loop over the frames in reverse order.
            xyz = self.ReadFrame(frame=nold - 1, instance=Coordinates3)
            if not hasFixedAtoms: xyz.Superimpose(reference)
            inew = nnew
            for n in range(nold - 2, -1, -1):
                # . Get the next reorientated frame.
                start = self.ReadFrame(frame=n, instance=Coordinates3)
                if not hasFixedAtoms: start.Superimpose(reference)
                # . Get the step.
                start.CopyTo(dxyz)
                dxyz.AddScaledMatrix(-1.0, xyz)
                dxyz.Scale(1.0 / float(ninsert + 1))
                # . Write out the frames.
                inew -= 1
                self.WriteFrame(xyz, frame=inew)
                for i in range(ninsert):
                    inew -= 1
                    xyz.AddScaledMatrix(1.0, dxyz)
                    self.WriteFrame(xyz, frame=inew)
#                    print i, inew
# . Make start the new stop.
                xyz = start
            # . Don't need to write out the last (first) frame as this is unchanged.
            # . Reset the number of frames.
            self.frames = nnew
コード例 #18
0
    def Parse(self, log=logFile):
        """Parse the data on the file."""
        if not self.QPARSED:
            # . Initialization.
            if LogFileActive(log): self.log = log
            # . Open the file.
            self.Open()
            try:
                # . Keyword line.
                self.title = self.GetLine()
                # . Number of atoms.
                items = self.GetTokens(converters=(int, ))
                natoms = items[0]
                # . The coordinate data.
                items = self.GetFixedFormatArray(3 * natoms,
                                                 _XYZNUMBER,
                                                 _XYZWIDTH,
                                                 converter=float,
                                                 default=0.0)
                self.xyz = Coordinates3.WithExtent(natoms)
                for n in range(natoms):
                    for i in range(3):
                        self.xyz[n, i] = items[3 * n + i]
                # . Symmetry data - optional.
                items = self.GetFixedFormatArray(3,
                                                 _SYMMETRYNUMBER,
                                                 _SYMMETRYWIDTH,
                                                 converter=float,
                                                 default=0.0,
                                                 QWARNING=False)
                self.symmetryParameters = SymmetryParameters()
                self.symmetryParameters.SetCrystalParameters(
                    items[0], items[1], items[2], 90.0, 90.0, 90.0)
            except EOFError:
                pass
# . Close the file.
            self.WarningStop()
            self.Close()
            # . Set the parsed flag and some other options.
            self.log = None
            self.QPARSED = True
コード例 #19
0
def AveragePositions(*arguments, **keywordArguments):
    """Calculate the average positions for selected particles."""

    # . Initialization.
    positions = None

    # . Process arguments.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Get the selection (or all particles otherwise).
    selection = keywordArguments.pop("selection", None)
    if selection is None:
        selection = Selection.FromIterable(range(len(system.atoms)))
    _CheckForUnknownOptions(keywordArguments)

    # . Get the size of the problem.
    n = len(selection)
    if n > 0:

        # . Allocate space.
        positions = Coordinates3.WithExtent(n)
        positions.Set(0.0)

        # . Loop over trajectory frames.
        numberFrames = 0
        for trajectory in trajectories:
            trajectory.ReadHeader()
            while trajectory.RestoreOwnerData():
                frame = system.coordinates3
                for (p, i) in enumerate(selection):
                    positions[p, 0] += frame[i, 0]
                    positions[p, 1] += frame[i, 1]
                    positions[p, 2] += frame[i, 2]
            trajectory.ReadFooter()
            trajectory.Close()
            numberFrames += len(trajectory)

        # . Scale.
        if numberFrames > 0: positions.Scale(1.0 / float(numberFrames))

    return positions
コード例 #20
0
 def _ParseXYZ ( self ):
     """Parse a Cartesian coordinate geometry specification."""
     self.atomicNumbers = []
     xyz                = []
     while True:
         tokens  = self.GetTokens ( converters = [ MopacInputFileReader.GetAtomicNumber, float, None, float, None, float, None ] )
         ntokens = len ( tokens )
         if ntokens == 0:
             break
         elif ntokens >= 7:
             self.atomicNumbers.append ( tokens[0] )
             xyz.append ( [ tokens[1], tokens[3], tokens[5] ] )
         else:
             self.Warning ( "Insufficient number of tokens ({:d}) on Cartesian coordinate input line.".format ( ntokens ), True )
     # . Create the coordinates.
     self.coordinates3 = Coordinates3.WithExtent ( len ( self.atomicNumbers ) )
     self.coordinates3.Set ( 0.0 )
     for ( i, ( x, y, z ) ) in enumerate ( xyz ):
         self.coordinates3[i,0] = x
         self.coordinates3[i,1] = y
         self.coordinates3[i,2] = z
コード例 #21
0
    def _ParseZMatrix ( self ):
        """Parse a Z-matrix geometry specification."""
        converters = [ MopacInputFileReader.GetAtomicNumber, float, None, float, None, float, None ]
        ncards     = 0
        oldfatal   = self.nfatal
        self.atomicNumbers = []
        zmatrixcards       = []
        while True:
            tokens  = self.GetTokens ( converters = converters )
            ntokens = len ( tokens )
            if ntokens == 0:
                break
            else:
                # . Append int to the converters for the first three cards.
                if ( ncards < 3 ): converters.append ( int )
                # . Basic checks on cards and tokens.
                if ( ( ncards == 0 ) and ( ntokens >=  7 ) ) or ( ( ncards == 1 ) and ( ntokens >=  8 ) ) or ( ( ncards == 2 ) and ( ntokens >=  9 ) ) or ( ( ncards >  2 ) and ( ntokens >= 10 ) ):
                    card = [ tokens[1], tokens[3], tokens[5] ]
                    if ( ncards > 0 ): card.append ( tokens[7] - 1 )
                    if ( ncards > 1 ): card.append ( tokens[8] - 1 )
                    if ( ncards > 2 ): card.append ( tokens[9] - 1 )
                    # . Check that the atom number values are valid.
                    QOK = True
                    for i in card[3:]:
                        QOK = QOK and ( i >= 0 ) and ( i < ncards )
                    if QOK:
                        ncards += 1
                        self.atomicNumbers.append ( tokens[0] )
                        zmatrixcards.append       ( card      )
                    else: self.Warning ( "Invalid atom number specification on Z-matrix input line.", True )
                else: self.Warning ( "Insufficient number of tokens ({:d}) on Z-matrix input line.".format ( ntokens ), True )
        # . Create the coordinates if there have been no fatal errors during the reading process.
        if self.nfatal == oldfatal:
            self.coordinates3 = Coordinates3.WithExtent ( len ( self.atomicNumbers ) )
            self.coordinates3.Set ( 0.0 )
            direction = Vector3.Null ( )
            for ( i, card ) in enumerate ( zmatrixcards ):
                if   i == 1:
                    direction.Set ( 0.0 )
                    direction[0] = 1.0
#                    direction.BasisVector ( 0 ) # . x-direction.
                    QOK = self.coordinates3.BuildPointFromDistance              ( i, card[3],                   card[0],          direction )
                elif i == 2:
                    direction.Set ( 0.0 )
                    direction[1] = 1.0
#                    direction.BasisVector ( 1 ) # . y-direction.
                    QOK = self.coordinates3.BuildPointFromDistanceAngle         ( i, card[3], card[4],          card[0], card[1], direction )
                elif i > 2:
                    QOK = self.coordinates3.BuildPointFromDistanceAngleDihedral ( i, card[3], card[4], card[5], card[0], card[1], card[2]   )
#                elif i > 1:
#                    # . Check for co-linear atoms.
#                    if math.fabs ( card[1] - 180.0 ) <= _LINEARTOLERANCE:
#                        j = card[3]
#                        k = card[4]
#                        for c in range ( 3 ):
#                            direction[c] = self.coordinates3[j,c] - self.coordinates3[k,c]
#                        direction.Normalize ( )
#                        QOK = self.coordinates3.BuildPointFromDistance ( i, j, card[0], direction )
#                    else:
#                        if i == 2:
#                            direction.BasisVector ( 1 ) # . y-direction.
#                            QOK = self.coordinates3.BuildPointFromDistanceAngle         ( i, card[3], card[4],          card[0], card[1], direction )
#                        else:
#                    # . Check for linear atoms.
#                            QOK = self.coordinates3.BuildPointFromDistanceAngleDihedral ( i, card[3], card[4], card[5], card[0], card[1], card[2]   )
                if not QOK:
                    self.Warning ( "Unable to build Cartesian coordinates from Z-matrix card number {:d}.".format ( i+1 ), True )
                    break
コード例 #22
0
 def Energy(self, log=logFile, doGradients=False):
     """Calculate the energy and, optionally, the gradients for a system."""
     # . Initialization.
     tStartEnergy = self.cpuTimer.Current()
     # . Do nothing if coordinates and an energy model are absent.
     if (self.coordinates3 is None) or (self.energyModel is None): return
     # . Set up configuration.
     self.configuration.ClearTemporaryAttributes()
     self.configuration.SetTemporaryAttribute("energyTerms", EnergyTerms())
     # . Make this clearer here (no need to reallocate each time).
     if doGradients:
         g = Coordinates3.WithExtent(len(self.atoms))
         g.Set(0.0)
         self.configuration.SetTemporaryAttribute("gradients3", g)
         if self.symmetry is not None:
             self.configuration.SetTemporaryAttribute(
                 "symmetryParameterGradients", SymmetryParameterGradients())
     # . Alias various data structures.
     em = self.energyModel
     et = self.configuration.energyTerms
     fa = None
     crd = self.configuration.coordinates3
     grd = getattr(self.configuration, "gradients3", None)
     if self.hardConstraints is not None:
         fa = self.hardConstraints.fixedAtoms
     self.timings["Initialization"] += (self.cpuTimer.Current() -
                                        tStartEnergy)
     # . Calculate MM terms.
     if (em.mmModel is not None) and (em.mmTerms is not None):
         for mmterm in em.mmTerms:
             tStart = self.cpuTimer.Current()
             results = mmterm.Energy(crd, grd)
             et.Append(results)
             self.timings[results[0]] += (self.cpuTimer.Current() - tStart)
     # . Calculate NB terms.
     if em.nbModel is not None:
         tStart = self.cpuTimer.Current()
         em.nbModel.SetUp(em.mmAtoms,
                          em.qcAtoms,
                          em.ljParameters,
                          em.ljParameters14,
                          fa,
                          em.interactions14,
                          em.exclusions,
                          self.symmetry,
                          self.connectivity.isolates,
                          self.configuration,
                          log=log)
         tStop = self.cpuTimer.Current()
         self.timings["NB Set Up"] += (tStop - tStart)
         et.Extend(em.nbModel.Energy(self.configuration))
         self.timings["NB Evaluation"] += (self.cpuTimer.Current() - tStop)
     # . Calculate QC and QC/MM electrostatic terms.
     if em.qcModel is not None:
         tStart = self.cpuTimer.Current()
         if (em.nbModel is not None):
             em.nbModel.QCMMPotentials(self.configuration)
             tStop = self.cpuTimer.Current()
             self.timings["QC/MM Potentials"] += (tStop - tStart)
             tStart = tStop
         et.Extend(
             em.qcModel.EnergyWithTimings(em.qcAtoms,
                                          em.qcParameters,
                                          self.electronicState,
                                          self.configuration,
                                          self.cpuTimer,
                                          self.timings,
                                          log=log))
         tStop = self.cpuTimer.Current()
         self.timings["QC Evaluation"] += (tStop - tStart)
         if (em.nbModel is not None) and doGradients:
             tStart = tStop
             em.nbModel.QCMMGradients(self.configuration)
             self.timings["QC/MM Gradients"] += (self.cpuTimer.Current() -
                                                 tStart)
     # . Calculate the soft constraint terms.
     if em.softConstraints is not None:
         tStart = self.cpuTimer.Current()
         (scEnergy, scState) = em.softConstraints.Energy(crd, grd)
         self.configuration.SetTemporaryAttribute("scState", scState)
         et.Append(scEnergy)
         self.timings["Soft Constraint"] += (self.cpuTimer.Current() -
                                             tStart)
     # . Calculate the total energy.
     tStart = self.cpuTimer.Current()
     et.Total()
     # . Zero out unnecessary gradient terms.
     if (fa is not None) and doGradients: grd.SetRowSelection(fa, 0.0)
     # . Print the energy terms if necessary.
     if LogFileActive(log):
         if doGradients: et.RMSGradient(grd.RMSValue())
         et.Summary(log=log)
     # . Finish up.
     tStop = self.cpuTimer.Current()
     self.timings["Energy"] += (tStop - tStartEnergy)
     self.timings["Finalization"] += (tStop - tStart)
     self.numberOfEnergyCalls += 1
     return et.potentialEnergy
コード例 #23
0
    def Parse(self, log=logFile):
        """Parsing."""
        if not self.QPARSED:
            # . Initialization.
            if LogFileActive(log): self.log = log
            self.molrecords = []
            # . Open the file.
            self.Open()
            # . Parse the data.
            try:
                # . Parse all entries.
                QCONTINUE = True
                while QCONTINUE:
                    # . Header block.
                    # . Molecule name.
                    label = self.GetLine(QWARNING=False)
                    # . Skip lines 1 and 2 which are not parsed.
                    self.GetLine()
                    self.GetLine()
                    # . Connection table.
                    # . Counts line - only atom and bond numbers are parsed.
                    (natoms, nbonds) = self.GetFixedFormatTokens(
                        (0, 3, int, 0), (3, 6, int, 0))
                    # . Initialize atom and coordinates data structures.
                    atomicNumbers = []
                    bonds = []
                    charges = []
                    coordinates3 = Coordinates3.WithExtent(natoms)
                    mchg = {}
                    miso = {}
                    mrad = {}
                    coordinates3.Set(0.0)
                    # . Read the atom lines.
                    for n in range(natoms):
                        (x, y, z, atomicNumber,
                         charge) = self.GetFixedFormatTokens(
                             (0, 10, float, 0.0), (10, 20, float, 0.0),
                             (20, 30, float, 0.0),
                             (31, 34, PeriodicTable.AtomicNumber, -1),
                             (36, 39, int, 0))
                        atomicNumbers.append(atomicNumber)
                        charges.append(_CHARGECODES.get(charge, 0))
                        coordinates3[n, 0] = x
                        coordinates3[n, 1] = y
                        coordinates3[n, 2] = z
                    # . Read the bond lines.
                    for n in range(nbonds):
                        (atom1, atom2, code) = self.GetFixedFormatTokens(
                            (0, 3, int, 0), (3, 6, int, 0), (6, 9, int, 0))
                        if (atom1 <= 0) or (atom1 > natoms) or (
                                atom2 <= 0) or (atom2 > natoms):
                            self.Warning(
                                "Bond atom indices out of range: {:d}, {:d}.".
                                format(atom1, atom2), True)
                        bonds.append((atom1 - 1, atom2 - 1,
                                      _MOLBONDTYPES.get(code,
                                                        UndefinedBond())))
                    # . Properties lines.
                    while True:
                        line = self.GetLine()
                        if line.startswith("M  CHG"):
                            self.ParsePropertiesLine(line, mchg)
                        elif line.startswith("M  ISO"):
                            self.ParsePropertiesLine(line, miso)
                        elif line.startswith("M  RAD"):
                            self.ParsePropertiesLine(line, mrad)
                        elif line.startswith("M  END"):
                            break
                    # . Store the data.
                    self.molrecords.append(
                        (label, atomicNumbers, bonds, charges, coordinates3,
                         mchg, miso, mrad))
                    # . Check for an SDF terminator.
                    QCONTINUE = False
                    while True:
                        line = self.GetLine(QWARNING=False)
                        if line == "$$$$":
                            QCONTINUE = True
                            break
            except EOFError:
                pass
# . Close the file.
            self.WarningStop()
            self.Close()
            # . Set the parsed flag and some other options.
            self.log = None
            self.QPARSED = True
コード例 #24
0
 def ToSystem(self,
              altLoc=_UNDEFINEDCHARACTER,
              modelNumber=_DEFAULTMODELNUMBER,
              embeddedHydrogens=False):
     """Return a system from the model."""
     system = None
     if self.QFINALIZED:
         # . Initialization.
         index = 0
         atomPaths = []
         majorSeparator = Sequence.defaultAttributes["labelSeparator"]
         minorSeparator = Sequence.defaultAttributes["fieldSeparator"]
         systemAtoms = []
         undefined = []
         xyz = []
         # . Loop over entities.
         entities = list(self.entities.values())
         entities.sort(key=mmCIFModelEntity.GetIndex)
         entityLabels = {}
         for entity in entities:
             # . Entity label.
             if entity.asymlabel == _UNDEFINEDCHARACTER:
                 entityLabel = _DefaultLabel
             else:
                 entityLabel = entity.asymlabel
             if (entity.asymlabel != entity.label) and (
                     entity.label != _UNDEFINEDCHARACTER):
                 entityLabel += (minorSeparator + entity.label)
             entityLabels[entity] = entityLabel
             # . Loop over components.
             components = list(entity.components.values())
             components.sort(key=mmCIFModelComponent.GetIndex)
             for component in components:
                 # . Component path.
                 fields = []
                 for item in (component.name, component.sequencenumber,
                              component.insertioncode):
                     if item == _UNDEFINEDCHARACTER:
                         fields.append(_DefaultLabel)
                     else:
                         fields.append(item)
                 n = 3
                 for item in reversed(fields):
                     if item == _DefaultLabel: n -= 1
                     else: break
                 componentLabel = minorSeparator.join(fields[0:max(n, 1)])
                 # . Loop over atoms - putting hydrogens at the end if necessary.
                 atoms = list(component.atoms.values())
                 if embeddedHydrogens:
                     atoms.sort(key=mmCIFModelAtom.GetIndex)
                 else:
                     atoms.sort(
                         key=mmCIFModelAtom.GetNonEmbeddedHydrogenIndex)
                 # . Generate atoms and associated data.
                 for atom in atoms:
                     systemAtoms.append(
                         Atom(atomicNumber=atom.atomicNumber,
                              formalCharge=atom.formalCharge))
                     if atom.label == _UNDEFINEDCHARACTER:
                         atomLabel = _DefaultLabel
                     else:
                         atomLabel = atom.label
                     atomPaths.append(entityLabel + majorSeparator +
                                      componentLabel + majorSeparator +
                                      atomLabel)
                     (QUNDEFINED, x, y,
                      z) = atom.GetCoordinateData(altLoc, modelNumber)
                     if QUNDEFINED: undefined.append(index)
                     xyz.append((x, y, z))
                     index += 1
         # . Make the sequence.
         sequence = Sequence.FromAtomPaths(atomPaths, atoms=systemAtoms)
         # . Make the system.
         system = System.FromSequence(sequence)
         if self.label is not None: system.label = self.label
         # . Coordinates.
         coordinates3 = Coordinates3.WithExtent(len(systemAtoms))
         for (i, (x, y, z)) in enumerate(xyz):
             coordinates3[i, 0] = x
             coordinates3[i, 1] = y
             coordinates3[i, 2] = z
         system.coordinates3 = coordinates3
         # . Undefined coordinates.
         if len(undefined) > 0:
             for i in undefined:
                 system.coordinates3.FlagCoordinateAsUndefined(i)
         # . Define polymer data.
         for oldEntity in entities:
             if isinstance(oldEntity, mmCIFModelPolymerEntity):
                 newEntity = system.sequence.childIndex.get(
                     entityLabels[oldEntity])
                 system.sequence.linearPolymers.append ( SequenceLinearPolymer ( isCyclic               = oldEntity.QCYCLIC      , \
                                                                                 leftTerminalComponent  = newEntity.children[ 0] , \
                                                                                 rightTerminalComponent = newEntity.children[-1] ) )
         # . Finish up.
         return system
コード例 #25
0
    def Parse(self, log=logFile):
        """Parsing."""
        if not self.QPARSED:
            # . Initialization.
            if LogFileActive(log): self.log = log
            # . Open the file.
            self.Open()
            # . Parse the data.
            try:
                # . Header.
                self.label = self.GetLine()
                # . More description - ignored.
                self.GetLine()
                # . First definition line.
                (natoms, ox, oy, oz) = self.GetFixedFormatTokens(
                    (0, 5, int, 0), (5, 17, float, 0.0), (17, 29, float, 0.0),
                    (29, 41, float, 0.0))
                hasOrbitals = (natoms < 0)
                if hasOrbitals: natoms = abs(natoms)
                # . Grid axis definitions - number of points and increment vector.
                griddata = []
                ngrid = 1
                for (i, o) in enumerate((ox, oy, oz)):
                    items = self.GetFixedFormatTokens(
                        (0, 5, int, 0), (5, 17, float, 0.0),
                        (17, 29, float, 0.0), (29, 41, float, 0.0))
                    n = items.pop(0)
                    h = items.pop(i) * UNITS_LENGTH_BOHRS_TO_ANGSTROMS
                    o *= UNITS_LENGTH_BOHRS_TO_ANGSTROMS
                    if (items[0] != 0.0) or (items[1] != 0.0):
                        self.Warning(
                            "Unable to handle grids whose increment vectors are not aligned along the Cartesian axes.",
                            False)
                    griddata.append({
                        "bins": n,
                        "binSize": h,
                        "lower": o - 0.5 * h
                    })
                    ngrid *= n
                # . Get the grid.
                self.grid = RegularGrid_FromDimensionData(griddata)
                # . Atom data.
                self.atomicNumbers = []
                self.coordinates3 = Coordinates3.WithExtent(natoms)
                for i in range(natoms):
                    (n, q, x, y, z) = self.GetFixedFormatTokens(
                        (0, 5, int, 0), (5, 17, float, 0.0),
                        (17, 29, float, 0.0), (29, 41, float, 0.0),
                        (41, 53, float, 0.0))
                    self.atomicNumbers.append(n)
                    self.coordinates3[i, 0] = x
                    self.coordinates3[i, 1] = y
                    self.coordinates3[i, 2] = z
                self.coordinates3.Scale(UNITS_LENGTH_BOHRS_TO_ANGSTROMS)
                # . Orbital data.
                if hasOrbitals:
                    indices = self.GetTokens()
                    for (i, index) in enumerate(indices):
                        indices[i] = int(index)
                    norbitals = indices.pop(0)
                    if norbitals != len(indices):
                        self.Warning(
                            "The number of orbitals does not match the number of orbital indices.",
                            True)
                    self.orbitalindices = indices
                else:
                    self.orbitalindices = None
                # . Field data.
                # . Unfortunately each row is written out separately so reading in has to be done by row as well.
                keys = []
                if hasOrbitals:
                    for index in self.orbitalindices:
                        keys.append("Orbital {:d}".format(index))
                else:
                    keys.append("Density")
                self.fielddata = {}
                for key in keys:
                    self.fielddata[key] = RealNDArray.WithExtents(
                        *self.grid.shape)
                nfields = len(keys)
                if nfields == 1:
                    fielddata = self.fielddata[keys[0]]  # []
                else:
                    fielddata = []
                    for key in keys:
                        fielddata.append(self.fielddata[key])
                nitems = griddata[2]["bins"] * nfields
                for ix in range(griddata[0]["bins"]):
                    for iy in range(griddata[1]["bins"]):
                        newdata = self.GetFixedFormatArray(nitems,
                                                           6,
                                                           13,
                                                           converter=float,
                                                           default=0.0)
                        if nfields == 1:
                            #                            fielddata.extend ( newdata )
                            for iz in range(nitems):
                                fielddata[ix, iy, iz] = newdata[iz]
                        else:
                            for ifield in range(nfields):
                                for (iz, i) in enumerate(
                                        range(ifield, nitems, nfields)):
                                    fielddata[ifield][ix, iy, iz] = newdata[i]
#                            for ifield in range ( nfields ):
#                                fielddata[ifield].extend ( newdata[ifield::nfields] )
            except EOFError:
                pass
# . Close the file.
            self.WarningStop()
            self.Close()
            # . Set the parsed flag and some other options.
            self.log = None
            self.QPARSED = True
コード例 #26
0
 def Energy(self, log=logFile, doGradients=False):
     """Calculate the energy and, optionally, the gradients for a system."""
     # . Do nothing if coordinates and an energy model are absent.
     if (self.coordinates3 is None) or (self.energyModel is None): return
     # . Set up configuration.
     self.configuration.ClearTemporaryAttributes()
     self.configuration.SetTemporaryAttribute("energyTerms", EnergyTerms())
     # . Make this clearer here (no need to reallocate each time).
     if doGradients:
         g = Coordinates3.WithExtent(len(self.atoms))
         g.Set(0.0)
         self.configuration.SetTemporaryAttribute("gradients3", g)
         if self.symmetry is not None:
             self.configuration.SetTemporaryAttribute(
                 "symmetryParameterGradients", SymmetryParameterGradients())
     # . Alias various data structures.
     em = self.energyModel
     et = self.configuration.energyTerms
     fa = None
     crd = self.configuration.coordinates3
     grd = getattr(self.configuration, "gradients3", None)
     if self.hardConstraints is not None:
         fa = self.hardConstraints.fixedAtoms
     # . Calculate MM terms.
     if (em.mmModel is not None) and (em.mmTerms is not None):
         for mmterm in em.mmTerms:
             et.Append(mmterm.Energy(crd, grd))
     # . Calculate NB terms.
     if em.nbModel is not None:
         em.nbModel.SetUp(em.mmAtoms,
                          em.qcAtoms,
                          em.ljParameters,
                          em.ljParameters14,
                          fa,
                          em.interactions14,
                          em.exclusions,
                          self.symmetry,
                          self.connectivity.isolates,
                          self.configuration,
                          log=log)
         et.Extend(em.nbModel.Energy(self.configuration))
     # . Calculate QC and QC/MM electrostatic terms.
     if em.qcModel is not None:
         if (em.nbModel is not None):
             em.nbModel.QCMMPotentials(self.configuration)
         et.Extend(
             em.qcModel.Energy(em.qcAtoms,
                               em.qcParameters,
                               self.electronicState,
                               self.configuration,
                               log=log))
         if (em.nbModel is not None) and doGradients:
             em.nbModel.QCMMGradients(self.configuration)
     # . Calculate the soft constraint terms.
     if em.softConstraints is not None:
         (scEnergy, scState) = em.softConstraints.Energy(crd, grd)
         self.configuration.SetTemporaryAttribute("scState", scState)
         et.Append(scEnergy)
     # . Calculate the total energy.
     et.Total()
     # . Zero out unnecessary gradient terms.
     if (fa is not None) and doGradients: grd.SetRowSelection(fa, 0.0)
     # . Print the energy terms if necessary.
     if LogFileActive(log):
         if doGradients: et.RMSGradient(grd.RMSValue())
         et.Summary(log=log)
     return et.potentialEnergy
コード例 #27
0
def CoordinateFluctuations(*arguments, **keywordArguments):
    """Calculate the coordinate fluctuations for selected particles."""

    # . Initialization.
    fluctuations = None

    # . Get the trajectory and associated system data.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Get the selection and the size of the problem.
    selection = keywordArguments.pop("selection", None)
    if selection is None:
        selection = Selection.FromIterable(range(len(system.atoms)))
    n = len(selection)

    # . Get the average positions.
    averagePositions = keywordArguments.pop("averagePositions", None)
    if averagePositions is None:
        averagePositions = AveragePositions(trajectories, selection=selection)

    # . Various other options.
    anisotropic = keywordArguments.pop("anisotropic", False)
    asBFactors = keywordArguments.pop("asBFactors", False)
    _CheckForUnknownOptions(keywordArguments)

    # . Continue processing.
    if (n > 0) and (averagePositions is not None):

        # . Allocate space.
        displacement = Coordinates3.WithExtent(n)
        if anisotropic: fluctuations = Real2DArray.WithExtents(n, 6)
        else: fluctuations = Real1DArray.WithExtent(n)
        displacement.Set(0.0)
        fluctuations.Set(0.0)

        # . Loop over trajectory frames.
        numberFrames = 0
        for trajectory in trajectories:
            trajectory.ReadHeader()
            while trajectory.RestoreOwnerData():
                frame = system.coordinates3
                if anisotropic:
                    for (p, i) in enumerate(selection):
                        dx = frame[i, 0] - averagePositions[p, 0]
                        dy = frame[i, 1] - averagePositions[p, 1]
                        dz = frame[i, 2] - averagePositions[p, 2]
                        fluctuations[p, 0] += dx * dx
                        fluctuations[p, 1] += dy * dx
                        fluctuations[p, 2] += dy * dy
                        fluctuations[p, 3] += dz * dx
                        fluctuations[p, 4] += dz * dy
                        fluctuations[p, 5] += dz * dz
                else:
                    for (p, i) in enumerate(selection):
                        fluctuations[p] += ( ( frame[i,0] - averagePositions[p,0] )**2 + \
                                             ( frame[i,1] - averagePositions[p,1] )**2 + \
                                             ( frame[i,2] - averagePositions[p,2] )**2 )
            trajectory.ReadFooter()
            trajectory.Close()
            numberFrames += len(trajectory)

        # . Scale.
        if numberFrames > 0: fluctuations.Scale(1.0 / float(numberFrames))

        # . Convert to B-factors if necessary.
        if asBFactors:
            conversionFactor = 8.0 * math.pi**2
            if not anisotropic: conversionFactor /= 3.0
            fluctuations.Scale(conversionFactor)

    # . Finish up.
    return fluctuations
コード例 #28
0
def GenerateVanDerWaalsSurface(system,
                               gridangularmomentum=21,
                               log=logFile,
                               qcAtomsOnly=False,
                               scalingfactors=[1.0]):
    """Generate a superposition of van der Waals surfaces represented by grid points."""

    # . QC atoms only (including link atoms).
    if qcAtomsOnly:
        qcAtoms = system.energyModel.qcAtoms
        atomicNumbers = qcAtoms.GetAtomicNumbers()
        coordinates3 = qcAtoms.GetCoordinates3(system.coordinates3)
    # . All atoms.
    else:
        atomicNumbers = system.atoms.GetItemAttributes("atomicNumber")
        coordinates3 = system.coordinates3

    # . Find the number of atoms.
    natoms = len(atomicNumbers)

    # . Set radii.
    radii = Real1DArray.WithExtent(natoms)
    for (i, n) in enumerate(atomicNumbers):
        radii[i] = PeriodicTable.Element(n).vdwRadius

    # . Get the grid points for a single center.
    (basicgrid, weights) = LebedevLaikovGrid_GetGridPoints(gridangularmomentum)

    # . Allocate space for the possible number of grid points.
    npossible = natoms * basicgrid.rows * len(scalingfactors)
    gridPoints = Coordinates3.WithExtent(npossible)
    gridPoints.Set(0.0)

    # . Initialization.
    nfound = 0
    atomgrid = Coordinates3.WithExtent(basicgrid.rows)
    translation = Vector3.Null()
    atomgrid.Set(0.0)

    # . Loop over scaling factors.
    for factor in scalingfactors:

        # . Loop over points.
        for i in range(natoms):

            # . Get the radius.
            iradius = factor * radii[i]

            # . Get the translation.
            translation[0] = coordinates3[i, 0]
            translation[1] = coordinates3[i, 1]
            translation[2] = coordinates3[i, 2]

            # . Get the scaled grid centered at the point.
            basicgrid.CopyTo(atomgrid)
            atomgrid.Scale(iradius)
            atomgrid.Translate(translation)

            # . Remove points that are within the current scaled radii of other points.
            for p in range(atomgrid.rows):
                QOK = True
                x = atomgrid[p, 0]
                y = atomgrid[p, 1]
                z = atomgrid[p, 2]
                for j in range(natoms):
                    if j != i:
                        dx = coordinates3[j, 0] - x
                        dy = coordinates3[j, 1] - y
                        dz = coordinates3[j, 2] - z
                        jradius2 = (factor * radii[j])**2
                        if (dx**2 + dy**2 + dz**2) <= jradius2:
                            QOK = False
                            break
                if QOK:
                    gridPoints[nfound, 0] = x
                    gridPoints[nfound, 1] = y
                    gridPoints[nfound, 2] = z
                    nfound += 1

    # . Reduce the array size if necessary.
    if nfound < npossible:
        newpoints = Coordinates3.WithExtent(nfound)
        for p in range(nfound):
            newpoints[p, 0] = gridPoints[p, 0]
            newpoints[p, 1] = gridPoints[p, 1]
            newpoints[p, 2] = gridPoints[p, 2]
        gridPoints = newpoints

    # . Create a system.
#    from pBabel  import XYZFile_FromSystem
#    from pMolecule import System
#    ngrid = gridPoints.rows
#    junk = System ( ngrid * [ 1 ] )
#    junk.coordinates3 = gridPoints
#    XYZFile_FromSystem ( "junk.xyz", junk )

# . Do some printing.
    if LogFileActive(log):
        summary = log.GetSummary()
        summary.Start("van der Waals Surface Generation Summary")
        summary.Entry("Atoms", "{:d}".format(natoms))
        summary.Entry("Surfaces", "{:d}".format(len(scalingfactors)))
        summary.Entry("Found Points", "{:d}".format(nfound))
        summary.Entry("Possible Points", "{:d}".format(npossible))
        summary.Stop()

    # . Finish up.
    return gridPoints