Skip to content

Commit

Permalink
Merge pull request #1 from Exabyte-io/feature/SOF-6013
Browse files Browse the repository at this point in the history
Feature/sof 6013
  • Loading branch information
azech-hqs committed Jul 27, 2022
2 parents f2d9c5c + 5582747 commit 37944e9
Show file tree
Hide file tree
Showing 17 changed files with 6,549 additions and 106 deletions.
74 changes: 66 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,70 @@
# template-definitions
[![npm version](https://badge.fury.io/js/%40exabyte-io%2Fade.js.svg)](https://badge.fury.io/js/%40exabyte-io%2Fade.js)
[![License: Apache](https://img.shields.io/badge/License-Apache-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)

Template repository for entity definition libraries in Javascript
# ade.js

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

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

### Installation

For usage within a javascript project:

```bash
npm install @exabyte-io/ade.js
```

For development:

```bash
git clone https://github.com/Exabyte-io/ade.js.git
```


### Contribution

This repository is an [open-source](LICENSE.md) work-in-progress and we welcome contributions.

We regularly deploy the latest code containing all accepted contributions online as part of the
[Mat3ra.com](https://mat3ra.com) platform, so contributors will see their code in action there.

See [ESSE](https://github.com/Exabyte-io/esse) for additional context regarding the data schemas used here.

Useful commands for development:

```bash
# run linter without persistence
npm run lint

# run linter and save edits
npm run lint:fix

# compile the library
npm run transpile

# run tests
npm run test
```

ADe
===

The`ADe` package sits just below the `WoDe` package in the Mat3ra workflow
ecosystem, where `ADe` houses entity definitions for:

- `Application` - uniquely determined by `name, [version], [build]`
- `Executable` - defined for a given application and accessible from application by name
- `Flavor` - defined for a given executable and accessible from executable by name
- `Template` - a jinja template for an application input file

The relevant data parameterizing these entities is housed in
the [Application Flavors](https://github.com/Exabyte-io/exabyte-application-flavors)
repository. This includes the supported applications, executables, flavors,
and defined templates.

Templates themselves are organized by application in a top-level `assets`
directory in `application-flavors` and the API for loading and working with templates can be found in
each application's `assets.js` module.
At build time, all templates are loaded and compiled into a single monolithic
JS file using `build_templates.js` so that it can be used in the client as well as in NodeJS.
This is how templates are consumed from `applicaton-flavors` in `ADe`.
5,727 changes: 5,727 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 15 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@exabyte-io/PROJECT_NAME",
"name": "@exabyte-io/ade.js",
"version": "0.0.0",
"description": "PROJECT_DESCRIPTION",
"description": "Application DEfinitions",
"scripts": {
"test": "nyc --reporter=text mocha --recursive --bail --require @babel/register/lib --require tests/setup.js tests",
"lint": "eslint src tests && prettier --write src tests",
Expand All @@ -13,7 +13,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/Exabyte-io/PROJECT_NAME.git"
"url": "https://github.com/Exabyte-io/ade.js.git"
},
"main": "dist/index.js",
"files": [
Expand All @@ -23,10 +23,10 @@
],
"author": "Exabyte Inc.",
"bugs": {
"url": "https://github.com/Exabyte-io/PROJECT_NAME/issues"
"url": "https://github.com/Exabyte-io/ade.js/issues"
},
"license": "Apache-2.0",
"homepage": "https://github.com/Exabyte-io/PROJECT_NAME",
"homepage": "https://github.com/Exabyte-io/ade.js",
"dependencies": {
"@babel/cli": "7.16.0",
"@babel/core": "7.16.0",
Expand All @@ -35,7 +35,16 @@
"@babel/preset-env": "7.16.4",
"@babel/preset-react": "7.16.7",
"@babel/register": "^7.16.0",
"@babel/runtime-corejs3": "7.16.8"
"@babel/runtime-corejs3": "7.16.8",
"@exabyte-io/application-flavors.js": "2022.7.24-0",
"@exabyte-io/code.js": "2022.7.19-0",
"@exabyte-io/made.js": "2022.6.15-0",
"@exabyte-io/periodic-table.js": "2022.6.8-0",
"lodash": "^4.17.21",
"mixwith": "^0.1.1",
"swig": "^1.4.2",
"underscore": "^1.13.3",
"underscore.string": "^3.3.4"
},
"devDependencies": {
"chai": "^4.3.4",
Expand All @@ -62,4 +71,3 @@
"*.{js,css}": "prettier --write"
}
}

114 changes: 114 additions & 0 deletions src/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import lodash from "lodash";
import { getAppTree, getAppData, allApplications } from "@exabyte-io/application-flavors.js";
import { NamedDefaultableInMemoryEntity } from "@exabyte-io/code.js/dist/entity";

import { Executable } from "./executable";
import { getApplicationConfig, getExecutableConfig } from "./tree";


export class Application extends NamedDefaultableInMemoryEntity {
static Executable = Executable;

constructor(config) {
const staticConfig = getApplicationConfig(config);
super({...staticConfig, ...config});
}

// TODO: extract this from application-flavors "global" default config for espresso 5.4.0
static get defaultConfig() {
return {
name: 'espresso',
shortName: 'qe',
version: '5.4.0',
summary: 'Quantum Espresso',
build: 'Default',
}
}

static create(config) {
return this.createFromNameVersionBuild(config);
}

static createFromNameVersionBuild({name, version = null, build = "Default"}) {
return new Application({name, version, build});
}

getExecutables() {
return this.executables;
}

getBuilds() {
const data = getAppData(this.prop("name"));
const {versions} = data;
const builds = ["Default"];
versions.map((v) => v.build && builds.push(v.build));
return lodash.uniq(builds);
}

getVersions() {
const data = getAppData(this.prop("name"));
const {versions} = data;
const these = versions.map((v) => v.version);
return lodash.uniq(these);
}

static getUniqueAvailableNames() {
return allApplications;
}

getExecutableByName(name = null) {
return new this.constructor.Executable(
getExecutableConfig({
appName: this.prop("name"),
execName: name,
})
);
}

getExecutableByConfig(config) {
return config ? this.getExecutableByName(config.name) : this.defaultExecutable;
}

get defaultExecutable() {
return this.getExecutableByName();
}

// override upon inheritance
get allowedModelTypes() {
return []
}

get summary() {
return this.prop("summary");
}

get version() {
return this.prop("version");
}

get build() {
return this.prop("build");
}

get shortName() {
return this.prop("shortName", this.prop("name"));
}

get executables() {
const tree = getAppTree(this.prop("name"));
return Object.keys(tree).map(key => {
return new this.constructor.Executable(
Object.assign({}, tree[key], {name: key})
)
})
}

get hasAdvancedComputeOptions() {
return this.prop("hasAdvancedComputeOptions");
}

get isLicensed() {
return this.prop("isLicensed");
}

}
4 changes: 4 additions & 0 deletions src/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { NWChemTotalEnergyContextProvider } from "./context/providers/nwchem/providers";
export { QEPWXContextProvider, QENEBContextProvider } from "./context/providers/espresso/providers";
export { VASPContextProvider, VASPNEBContextProvider } from "./context/providers/vasp/providers";
export { ExecutableContextProvider } from "./context/providers"
10 changes: 10 additions & 0 deletions src/context/providers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ContextProvider } from "@exabyte-io/code.js/dist/context";

export class ExecutableContextProvider extends ContextProvider {
constructor(config) {
super({
...config,
domain: "executable"
});
}
}
112 changes: 112 additions & 0 deletions src/context/providers/espresso/providers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import _ from "underscore";
import lodash from "lodash";
import { mix } from "mixwith";
import s from "underscore.string";

import { Made } from "@exabyte-io/made.js";
import { PERIODIC_TABLE } from "@exabyte-io/periodic-table.js";

import {
MaterialContextMixinBuilder,
MaterialsContextMixinBuilder,
MaterialsSetContextMixin,
MethodDataContextMixin,
WorkflowContextMixin,
JobContextMixin
} from "@exabyte-io/code.js/dist/context";
import { ExecutableContextProvider } from "../../providers";

export class QEPWXContextProvider extends mix(ExecutableContextProvider).with(
MaterialContextMixinBuilder(Made.Material),
MethodDataContextMixin,
WorkflowContextMixin,
JobContextMixin,
) {

get atomSymbols() {return this.material.Basis.uniqueElements}

get atomicPositionsWithoutConstraints() {return this.material.Basis.atomicPositions}

get atomicPositions() {return this.material.Basis.atomicPositionsWithConstraints};

/*
* @NOTE: Overriding getData makes this provider "stateless", ie. delivering data from scratch each time and not
* considering the content of `this.data`, and `this.isEdited` field(s).
*/
getData() {

// the below values are read from PlanewaveDataManager instead
// ECUTWFC = 40;
// ECUTRHO = 200;

const IBRAV = 0;

return {
IBRAV,
RESTART_MODE: this.RESTART_MODE,
NAT: this.atomicPositions.length,
NTYP: this.atomSymbols.length,
ATOMIC_POSITIONS: this.atomicPositions.join('\n'),
ATOMIC_POSITIONS_WITHOUT_CONSTRAINTS: this.atomicPositionsWithoutConstraints.join('\n'),
CELL_PARAMETERS: this.CELL_PARAMETERS,
ATOMIC_SPECIES: this.ATOMIC_SPECIES,
}
}

get RESTART_MODE() {
return (this.job.parentJob || this.workflow.hasRelaxation) ? 'restart' : 'from_scratch';
}

getPseudoBySymbol(symbol) {
return (this.methodData.pseudo || []).find(p => p.element === symbol);
}

get ATOMIC_SPECIES() {
// atomic species with pseudopotentials
return _.map(this.atomSymbols, (symbol) => {
const pseudo = this.getPseudoBySymbol(symbol);
return QEPWXContextProvider.symbolToAtomicSpecie(symbol, pseudo);
}).join('\n');
}

get CELL_PARAMETERS() {
return this.material.Lattice.vectorArrays.map(x => {
return x.map(y => {
return s.sprintf('%14.9f', y).trim();
}).join(' ');
}).join('\n');

}

static symbolToAtomicSpecie(symbol, pseudo) {
const el = PERIODIC_TABLE[symbol];
const filename = pseudo ? lodash.get(pseudo, 'filename', s.strRightBack(pseudo.path, '/')) : '';
return el ? s.sprintf('%s %f %s', symbol, el.atomic_mass, filename) : undefined;
}
}

export class QENEBContextProvider extends mix(ExecutableContextProvider).with(
MaterialContextMixinBuilder(Made.Material),
MaterialsContextMixinBuilder(Made.Material),
MaterialsSetContextMixin,
MethodDataContextMixin,
WorkflowContextMixin,
JobContextMixin,
) {

getData() {
const sortedMaterials = this.sortMaterialsByIndexInSet(this.materials);
const PWXContexts = sortedMaterials.map(material => {
const context = Object.assign({}, this.config.context, {material: material});
const config = Object.assign({}, this.config, {context});
return new QEPWXContextProvider(config).getData();
});

return {
..._.omit(PWXContexts[0], ["ATOMIC_POSITIONS", "ATOMIC_POSITIONS_WITHOUT_CONSTRAINTS"]),
FIRST_IMAGE: PWXContexts[0].ATOMIC_POSITIONS,
LAST_IMAGE: PWXContexts[PWXContexts.length - 1].ATOMIC_POSITIONS,
INTERMEDIATE_IMAGES: PWXContexts.slice(1, PWXContexts.length - 1).map(data => data.ATOMIC_POSITIONS),
}
}
}
Loading

0 comments on commit 37944e9

Please sign in to comment.