Skip to content

Commit 37944e9

Browse files
authored
Merge pull request #1 from Exabyte-io/feature/SOF-6013
Feature/sof 6013
2 parents f2d9c5c + 5582747 commit 37944e9

File tree

17 files changed

+6549
-106
lines changed

17 files changed

+6549
-106
lines changed

README.md

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,70 @@
1-
# template-definitions
1+
[![npm version](https://badge.fury.io/js/%40exabyte-io%2Fade.js.svg)](https://badge.fury.io/js/%40exabyte-io%2Fade.js)
2+
[![License: Apache](https://img.shields.io/badge/License-Apache-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
23

3-
Template repository for entity definition libraries in Javascript
4+
# ade.js
45

5-
See [here](https://docs.github.com/en/github-ae@latest/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)
6-
for details on how to use this repository.
6+
ade.js houses entity definitions for use in the Mat3ra platform.
77

8-
Included is a simple `template.py` analog to `cookiecutter` which will prompt
9-
the user for some information and then write out templated values in select files.
10-
After usage, the `template.py` file can be removed and the `README.md` and associated
11-
`files` can be committed.
128

9+
### Installation
10+
11+
For usage within a javascript project:
12+
13+
```bash
14+
npm install @exabyte-io/ade.js
15+
```
16+
17+
For development:
18+
19+
```bash
20+
git clone https://github.com/Exabyte-io/ade.js.git
21+
```
22+
23+
24+
### Contribution
25+
26+
This repository is an [open-source](LICENSE.md) work-in-progress and we welcome contributions.
27+
28+
We regularly deploy the latest code containing all accepted contributions online as part of the
29+
[Mat3ra.com](https://mat3ra.com) platform, so contributors will see their code in action there.
30+
31+
See [ESSE](https://github.com/Exabyte-io/esse) for additional context regarding the data schemas used here.
32+
33+
Useful commands for development:
34+
35+
```bash
36+
# run linter without persistence
37+
npm run lint
38+
39+
# run linter and save edits
40+
npm run lint:fix
41+
42+
# compile the library
43+
npm run transpile
44+
45+
# run tests
46+
npm run test
47+
```
48+
49+
ADe
50+
===
51+
52+
The`ADe` package sits just below the `WoDe` package in the Mat3ra workflow
53+
ecosystem, where `ADe` houses entity definitions for:
54+
55+
- `Application` - uniquely determined by `name, [version], [build]`
56+
- `Executable` - defined for a given application and accessible from application by name
57+
- `Flavor` - defined for a given executable and accessible from executable by name
58+
- `Template` - a jinja template for an application input file
59+
60+
The relevant data parameterizing these entities is housed in
61+
the [Application Flavors](https://github.com/Exabyte-io/exabyte-application-flavors)
62+
repository. This includes the supported applications, executables, flavors,
63+
and defined templates.
64+
65+
Templates themselves are organized by application in a top-level `assets`
66+
directory in `application-flavors` and the API for loading and working with templates can be found in
67+
each application's `assets.js` module.
68+
At build time, all templates are loaded and compiled into a single monolithic
69+
JS file using `build_templates.js` so that it can be used in the client as well as in NodeJS.
70+
This is how templates are consumed from `applicaton-flavors` in `ADe`.

package-lock.json

Lines changed: 5727 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"name": "@exabyte-io/PROJECT_NAME",
2+
"name": "@exabyte-io/ade.js",
33
"version": "0.0.0",
4-
"description": "PROJECT_DESCRIPTION",
4+
"description": "Application DEfinitions",
55
"scripts": {
66
"test": "nyc --reporter=text mocha --recursive --bail --require @babel/register/lib --require tests/setup.js tests",
77
"lint": "eslint src tests && prettier --write src tests",
@@ -13,7 +13,7 @@
1313
},
1414
"repository": {
1515
"type": "git",
16-
"url": "https://github.com/Exabyte-io/PROJECT_NAME.git"
16+
"url": "https://github.com/Exabyte-io/ade.js.git"
1717
},
1818
"main": "dist/index.js",
1919
"files": [
@@ -23,10 +23,10 @@
2323
],
2424
"author": "Exabyte Inc.",
2525
"bugs": {
26-
"url": "https://github.com/Exabyte-io/PROJECT_NAME/issues"
26+
"url": "https://github.com/Exabyte-io/ade.js/issues"
2727
},
2828
"license": "Apache-2.0",
29-
"homepage": "https://github.com/Exabyte-io/PROJECT_NAME",
29+
"homepage": "https://github.com/Exabyte-io/ade.js",
3030
"dependencies": {
3131
"@babel/cli": "7.16.0",
3232
"@babel/core": "7.16.0",
@@ -35,7 +35,16 @@
3535
"@babel/preset-env": "7.16.4",
3636
"@babel/preset-react": "7.16.7",
3737
"@babel/register": "^7.16.0",
38-
"@babel/runtime-corejs3": "7.16.8"
38+
"@babel/runtime-corejs3": "7.16.8",
39+
"@exabyte-io/application-flavors.js": "2022.7.24-0",
40+
"@exabyte-io/code.js": "2022.7.19-0",
41+
"@exabyte-io/made.js": "2022.6.15-0",
42+
"@exabyte-io/periodic-table.js": "2022.6.8-0",
43+
"lodash": "^4.17.21",
44+
"mixwith": "^0.1.1",
45+
"swig": "^1.4.2",
46+
"underscore": "^1.13.3",
47+
"underscore.string": "^3.3.4"
3948
},
4049
"devDependencies": {
4150
"chai": "^4.3.4",
@@ -62,4 +71,3 @@
6271
"*.{js,css}": "prettier --write"
6372
}
6473
}
65-

src/application.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import lodash from "lodash";
2+
import { getAppTree, getAppData, allApplications } from "@exabyte-io/application-flavors.js";
3+
import { NamedDefaultableInMemoryEntity } from "@exabyte-io/code.js/dist/entity";
4+
5+
import { Executable } from "./executable";
6+
import { getApplicationConfig, getExecutableConfig } from "./tree";
7+
8+
9+
export class Application extends NamedDefaultableInMemoryEntity {
10+
static Executable = Executable;
11+
12+
constructor(config) {
13+
const staticConfig = getApplicationConfig(config);
14+
super({...staticConfig, ...config});
15+
}
16+
17+
// TODO: extract this from application-flavors "global" default config for espresso 5.4.0
18+
static get defaultConfig() {
19+
return {
20+
name: 'espresso',
21+
shortName: 'qe',
22+
version: '5.4.0',
23+
summary: 'Quantum Espresso',
24+
build: 'Default',
25+
}
26+
}
27+
28+
static create(config) {
29+
return this.createFromNameVersionBuild(config);
30+
}
31+
32+
static createFromNameVersionBuild({name, version = null, build = "Default"}) {
33+
return new Application({name, version, build});
34+
}
35+
36+
getExecutables() {
37+
return this.executables;
38+
}
39+
40+
getBuilds() {
41+
const data = getAppData(this.prop("name"));
42+
const {versions} = data;
43+
const builds = ["Default"];
44+
versions.map((v) => v.build && builds.push(v.build));
45+
return lodash.uniq(builds);
46+
}
47+
48+
getVersions() {
49+
const data = getAppData(this.prop("name"));
50+
const {versions} = data;
51+
const these = versions.map((v) => v.version);
52+
return lodash.uniq(these);
53+
}
54+
55+
static getUniqueAvailableNames() {
56+
return allApplications;
57+
}
58+
59+
getExecutableByName(name = null) {
60+
return new this.constructor.Executable(
61+
getExecutableConfig({
62+
appName: this.prop("name"),
63+
execName: name,
64+
})
65+
);
66+
}
67+
68+
getExecutableByConfig(config) {
69+
return config ? this.getExecutableByName(config.name) : this.defaultExecutable;
70+
}
71+
72+
get defaultExecutable() {
73+
return this.getExecutableByName();
74+
}
75+
76+
// override upon inheritance
77+
get allowedModelTypes() {
78+
return []
79+
}
80+
81+
get summary() {
82+
return this.prop("summary");
83+
}
84+
85+
get version() {
86+
return this.prop("version");
87+
}
88+
89+
get build() {
90+
return this.prop("build");
91+
}
92+
93+
get shortName() {
94+
return this.prop("shortName", this.prop("name"));
95+
}
96+
97+
get executables() {
98+
const tree = getAppTree(this.prop("name"));
99+
return Object.keys(tree).map(key => {
100+
return new this.constructor.Executable(
101+
Object.assign({}, tree[key], {name: key})
102+
)
103+
})
104+
}
105+
106+
get hasAdvancedComputeOptions() {
107+
return this.prop("hasAdvancedComputeOptions");
108+
}
109+
110+
get isLicensed() {
111+
return this.prop("isLicensed");
112+
}
113+
114+
}

src/context.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { NWChemTotalEnergyContextProvider } from "./context/providers/nwchem/providers";
2+
export { QEPWXContextProvider, QENEBContextProvider } from "./context/providers/espresso/providers";
3+
export { VASPContextProvider, VASPNEBContextProvider } from "./context/providers/vasp/providers";
4+
export { ExecutableContextProvider } from "./context/providers"

src/context/providers.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { ContextProvider } from "@exabyte-io/code.js/dist/context";
2+
3+
export class ExecutableContextProvider extends ContextProvider {
4+
constructor(config) {
5+
super({
6+
...config,
7+
domain: "executable"
8+
});
9+
}
10+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import _ from "underscore";
2+
import lodash from "lodash";
3+
import { mix } from "mixwith";
4+
import s from "underscore.string";
5+
6+
import { Made } from "@exabyte-io/made.js";
7+
import { PERIODIC_TABLE } from "@exabyte-io/periodic-table.js";
8+
9+
import {
10+
MaterialContextMixinBuilder,
11+
MaterialsContextMixinBuilder,
12+
MaterialsSetContextMixin,
13+
MethodDataContextMixin,
14+
WorkflowContextMixin,
15+
JobContextMixin
16+
} from "@exabyte-io/code.js/dist/context";
17+
import { ExecutableContextProvider } from "../../providers";
18+
19+
export class QEPWXContextProvider extends mix(ExecutableContextProvider).with(
20+
MaterialContextMixinBuilder(Made.Material),
21+
MethodDataContextMixin,
22+
WorkflowContextMixin,
23+
JobContextMixin,
24+
) {
25+
26+
get atomSymbols() {return this.material.Basis.uniqueElements}
27+
28+
get atomicPositionsWithoutConstraints() {return this.material.Basis.atomicPositions}
29+
30+
get atomicPositions() {return this.material.Basis.atomicPositionsWithConstraints};
31+
32+
/*
33+
* @NOTE: Overriding getData makes this provider "stateless", ie. delivering data from scratch each time and not
34+
* considering the content of `this.data`, and `this.isEdited` field(s).
35+
*/
36+
getData() {
37+
38+
// the below values are read from PlanewaveDataManager instead
39+
// ECUTWFC = 40;
40+
// ECUTRHO = 200;
41+
42+
const IBRAV = 0;
43+
44+
return {
45+
IBRAV,
46+
RESTART_MODE: this.RESTART_MODE,
47+
NAT: this.atomicPositions.length,
48+
NTYP: this.atomSymbols.length,
49+
ATOMIC_POSITIONS: this.atomicPositions.join('\n'),
50+
ATOMIC_POSITIONS_WITHOUT_CONSTRAINTS: this.atomicPositionsWithoutConstraints.join('\n'),
51+
CELL_PARAMETERS: this.CELL_PARAMETERS,
52+
ATOMIC_SPECIES: this.ATOMIC_SPECIES,
53+
}
54+
}
55+
56+
get RESTART_MODE() {
57+
return (this.job.parentJob || this.workflow.hasRelaxation) ? 'restart' : 'from_scratch';
58+
}
59+
60+
getPseudoBySymbol(symbol) {
61+
return (this.methodData.pseudo || []).find(p => p.element === symbol);
62+
}
63+
64+
get ATOMIC_SPECIES() {
65+
// atomic species with pseudopotentials
66+
return _.map(this.atomSymbols, (symbol) => {
67+
const pseudo = this.getPseudoBySymbol(symbol);
68+
return QEPWXContextProvider.symbolToAtomicSpecie(symbol, pseudo);
69+
}).join('\n');
70+
}
71+
72+
get CELL_PARAMETERS() {
73+
return this.material.Lattice.vectorArrays.map(x => {
74+
return x.map(y => {
75+
return s.sprintf('%14.9f', y).trim();
76+
}).join(' ');
77+
}).join('\n');
78+
79+
}
80+
81+
static symbolToAtomicSpecie(symbol, pseudo) {
82+
const el = PERIODIC_TABLE[symbol];
83+
const filename = pseudo ? lodash.get(pseudo, 'filename', s.strRightBack(pseudo.path, '/')) : '';
84+
return el ? s.sprintf('%s %f %s', symbol, el.atomic_mass, filename) : undefined;
85+
}
86+
}
87+
88+
export class QENEBContextProvider extends mix(ExecutableContextProvider).with(
89+
MaterialContextMixinBuilder(Made.Material),
90+
MaterialsContextMixinBuilder(Made.Material),
91+
MaterialsSetContextMixin,
92+
MethodDataContextMixin,
93+
WorkflowContextMixin,
94+
JobContextMixin,
95+
) {
96+
97+
getData() {
98+
const sortedMaterials = this.sortMaterialsByIndexInSet(this.materials);
99+
const PWXContexts = sortedMaterials.map(material => {
100+
const context = Object.assign({}, this.config.context, {material: material});
101+
const config = Object.assign({}, this.config, {context});
102+
return new QEPWXContextProvider(config).getData();
103+
});
104+
105+
return {
106+
..._.omit(PWXContexts[0], ["ATOMIC_POSITIONS", "ATOMIC_POSITIONS_WITHOUT_CONSTRAINTS"]),
107+
FIRST_IMAGE: PWXContexts[0].ATOMIC_POSITIONS,
108+
LAST_IMAGE: PWXContexts[PWXContexts.length - 1].ATOMIC_POSITIONS,
109+
INTERMEDIATE_IMAGES: PWXContexts.slice(1, PWXContexts.length - 1).map(data => data.ATOMIC_POSITIONS),
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)