UNPKG

molstar

Version:

A comprehensive macromolecular library.

130 lines 6.08 kB
/** * 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