molstar
Version:
A comprehensive macromolecular library.
130 lines • 6.08 kB
JavaScript
/**
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* Inspired by https://github.com/dgasmith/gau2grid.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { __awaiter, __generator } from "tslib";
import { Vec3 } from '../../mol-math/linear-algebra';
import { arrayMin } from '../../mol-util/array';
import { normalizeBasicOrder, SphericalFunctions } from './spherical-functions';
export function sphericalCollocation(grid, orbital, taskCtx) {
return __awaiter(this, void 0, void 0, function () {
var _a, basis, sphericalOrder, cutoffThreshold, baseCount, _i, _b, atom, _c, _d, shell, _e, _f, L, matrix, baseIndex, _g, _h, atom, _j, _k, shell, amIndex, _l, _m, L, alpha;
return __generator(this, function (_o) {
switch (_o.label) {
case 0:
_a = grid.params, basis = _a.basis, sphericalOrder = _a.sphericalOrder, cutoffThreshold = _a.cutoffThreshold;
baseCount = 0;
for (_i = 0, _b = basis.atoms; _i < _b.length; _i++) {
atom = _b[_i];
for (_c = 0, _d = atom.shells; _c < _d.length; _c++) {
shell = _d[_c];
for (_e = 0, _f = shell.angularMomentum; _e < _f.length; _e++) {
L = _f[_e];
if (L > 4) {
// TODO: will L > 4 be required? Would need to precompute more functions in that case.
throw new Error('Angular momentum L > 4 not supported.');
}
baseCount += 2 * L + 1;
}
}
}
matrix = new Float32Array(grid.npoints);
baseIndex = 0;
_g = 0, _h = basis.atoms;
_o.label = 1;
case 1:
if (!(_g < _h.length)) return [3 /*break*/, 8];
atom = _h[_g];
_j = 0, _k = atom.shells;
_o.label = 2;
case 2:
if (!(_j < _k.length)) return [3 /*break*/, 7];
shell = _k[_j];
amIndex = 0;
_l = 0, _m = shell.angularMomentum;
_o.label = 3;
case 3:
if (!(_l < _m.length)) return [3 /*break*/, 6];
L = _m[_l];
alpha = normalizeBasicOrder(L, orbital.alpha.slice(baseIndex, baseIndex + 2 * L + 1), sphericalOrder);
baseIndex += 2 * L + 1;
collocationBasis(matrix, grid, L, shell.coefficients[amIndex++], shell.exponents, atom.center, cutoffThreshold, alpha);
if (!taskCtx.shouldUpdate) return [3 /*break*/, 5];
return [4 /*yield*/, taskCtx.update({
message: 'Computing...',
current: baseIndex,
max: baseCount,
isIndeterminate: false,
})];
case 4:
_o.sent();
_o.label = 5;
case 5:
_l++;
return [3 /*break*/, 3];
case 6:
_j++;
return [3 /*break*/, 2];
case 7:
_g++;
return [3 /*break*/, 1];
case 8: return [2 /*return*/, matrix];
}
});
});
}
function collocationBasis(matrix, grid, L, coefficients, exponents, center, cutoffThreshold, alpha) {
var ncoeff = exponents.length;
var sphericalFunc = SphericalFunctions[L];
var cx = center[0], cy = center[1], cz = center[2];
var ny = grid.dimensions[1], nz = grid.dimensions[2];
var gdx = grid.delta[0], gdy = grid.delta[1], gdz = grid.delta[2];
var sx = grid.box.min[0], sy = grid.box.min[1], sz = grid.box.min[2];
var cutoffRadius = cutoffThreshold > 0
? Math.sqrt(-Math.log(cutoffThreshold) / arrayMin(exponents))
: 10000;
var cutoffSquared = cutoffRadius * cutoffRadius;
var radiusBox = getRadiusBox(grid, center, cutoffRadius);
var iMin = radiusBox[0][0], jMin = radiusBox[0][1], kMin = radiusBox[0][2];
var iMax = radiusBox[1][0], jMax = radiusBox[1][1], kMax = radiusBox[1][2];
for (var i = iMin; i <= iMax; i++) {
var x = sx + gdx * i - cx;
var oX = i * ny * nz;
for (var j = jMin; j <= jMax; j++) {
var y = sy + gdy * j - cy;
var oY = oX + j * nz;
for (var k = kMin; k <= kMax; k++) {
var z = sz + gdz * k - cz;
var R2 = x * x + y * y + z * z;
if (R2 > cutoffSquared) {
continue;
}
var gaussianSum = 0;
for (var c = 0; c < ncoeff; c++) {
gaussianSum +=
coefficients[c] * Math.exp(-exponents[c] * R2);
}
var sphericalSum = L === 0 ? alpha[0] : sphericalFunc(alpha, x, y, z);
matrix[k + oY] += gaussianSum * sphericalSum;
}
}
}
}
function getRadiusBox(grid, center, radius) {
var r = Vec3.create(radius, radius, radius);
var min = Vec3.scaleAndAdd(Vec3(), center, r, -1);
var max = Vec3.add(Vec3(), center, r);
Vec3.sub(min, min, grid.box.min);
Vec3.sub(max, max, grid.box.min);
Vec3.div(min, min, grid.delta);
Vec3.floor(min, min);
Vec3.max(min, min, Vec3());
Vec3.div(max, max, grid.delta);
Vec3.ceil(max, max);
Vec3.min(max, max, Vec3.subScalar(Vec3(), grid.dimensions, 1));
return [min, max];
}
//# sourceMappingURL=collocation.js.map