# rom.js

[![npm version](https://badge.fury.io/js/@simzero%2From.svg)](https://badge.fury.io/js/@simzero%2From)
[![Docker](https://badgen.net/badge/icon/docker?icon=docker&label)](https://github.com/orgs/simzero-oss/packages/container/package/rom-js)
[![stability-beta](https://img.shields.io/badge/stability-beta-33bbff.svg)]()
[![Join Slack](https://img.shields.io/badge/Join%20us%20on-Slack-e01563.svg)](https://join.slack.com/t/cfd-xyz/shared_invite/zt-12uquswo6-FFVy95vRjfMF~~t8j~UBHA)
[![License: LGPL v3](https://img.shields.io/badge/License-LGPL_v3-blue.svg)](https://github.com/simzero-oss/rom-js/blob/main/LICENSE)

`rom.js` is a JavaScript port for solving the online stage of reduced-order model (ROM) and visualizing the outputs on the web. The current version uses [OpenFOAM](https://www.openfoam.com) and [ITHACA-FV](https://github.com/mathLab/ITHACA-FV) for generating the CFD snapshots and the ROM.


`rom.js` is used in [http://cfd.xyz](http://cfd.xyz), check the website and the code at [cfd.xyz GitHub](https://github.com/simzero-oss/cfd-xyz-viewer).


This is a beta version, please handle it with care. Further features, optimizations and fixes are expected.

## Usage

This module can be directly installed with:

```console
npm install --save @simzero/rom
```

The  [standalone-templates](standalone-templates/) directory contains instructions and examples for using the module and generating CFD results with the available ROMs. Alternatively, the module and ROMs can be built and tested following the instructions described in [Option 1](#option-1-building-and-testing-with-docker-as-the-only-requirement) and [Option 2](#option-2-building-and-testing-by-natively-building-the-third-party-libraries).

A minimal example for steady-state cases can be found in [standalone-templates/steady.mjs](standalone-templates/steady.mjs). The main parts of this code are shown below:

```javascript
import rom from '@simzero/rom'
import Papa from 'papaparse'
import fs from 'fs'
import yargs from 'yargs'

// - Defining functions and configuration
...

(async () => {

  await rom.ready

  // - Loading ROM data (e.g. generated with the steady app)
  ...
  
  // - Defining reducedSteady
  const reduced = new rom.reducedSteady(nPhiU + nPhiP, nPhiU + nPhiP);

  // - Setting up grid and ROM data
  reduced.stabilization(argv.stabilization);
  reduced.nPhiU(nPhiU);
  reduced.nPhiP(nPhiP);
  reduced.nPhiNut(nPhiNut);
  reduced.nRuns(nRuns);
  reduced.nBC(nBC);

  reduced.readUnstructuredGrid(gridData);
  reduced.initialize();

  reduced.K().set(KData[0]);
  reduced.B().set(BData[0]);
  reduced.P().set(PData[0]);
  reduced.modes().set(modesData[0]);
  reduced.coeffL2().set(coeffL2Data[0]);
  reduced.mu().set(muData[0]);

  // - Loading turbulent related matrices and weights
  for (var i = 0; i < nPhiU; i ++ ){
    // - Loading data
    ...

    reduced.C().set(CData[0]);
    reduced.addCMatrix();
    reduced.Ct1().set(Ct1Data[0]);
    reduced.addCt1Matrix();
    reduced.Ct2().set(Ct2Data[0]);
    reduced.addCt2Matrix();
  }

  for (var i = 0; i < nPhiNut; i ++ ){
    // - Loading data
    ...

    reduced.weights().set(weightsData[0]);
    reduced.addWeights();
  }

  reduced.setRBF();

  // - Defining viscosity and solving for the given velocity
  reduced.nu(argv.nu);
  reduced.solveOnline(argv.Ux, argv.Uy);

  // - Reconstructing data from Eigen to VTK and exporting the grid
  reduced.reconstruct();
  const dataString = reduced.exportUnstructuredGrid();

  // - Saving the VTK file
  const outputFile = 'U_' + U + '_nu_' + nu + '.vtu';
  fs.writeFileSync(outputFile, dataString);

  reduced.delete();

})();
```

## Option 1 Building and testing with Docker as the only requirement 

This is the preferred and easiest method for working with this repository.

The [rom-js](https://github.com/orgs/simzero-oss/packages/container/package/rom-js) Docker image contains all the configuration and required third-party libraries for: 1) building the JavaScript module, 2) running OpenFOAM and 3) generating the ROM data using ITHACA-FV. The following versions are included in the image:

* [Emscripten](https://github.com/emscripten-core/emscripten) 3.1.1
* [npm](https://github.com/npm/cli) 8.5.3
* [node](https://github.com/nodejs/node) v14.18.2
* [Splinter](https://github.com/bgrimstad/splinter) v3.0 (compiled with emcc)
* [Eigen](https://gitlab.com/libeigen/eigen) v3.4.0 (compiled with emcc)
* [VTK](https://gitlab.kitware.com/vtk/vtk) v9.1 (compiled with emcc)
* [OpenFOAM](https://develop.openfoam.com/Development/openfoam) v2106
* [ITHACA-FV](https://github.com/mathLab/ITHACA-FV) 3.0 ([@carpemonf fork](https://github.com/carpemonf/ITHACA-FV))

### Requirements

* [Docker](https://www.docker.com/get-started) 20.10.12

### Building

The node version of the module can be executed outside a web browser with a back-end JavaScript runtime environment (Node.js). The following command builds both the node and browser version of the module:

```console
make all
```

### Generating the ROM data

The CFD snapshots are generated directly with OpenFOAM and later used in ITHACA-FV for generating the ROM. This results in hundreds of simulation executions and multiple GB of data. You can skip running this step by directly downloading the ROM data into the `surrogates` folder with:

```console
make data
```

Alternatively, You can also create the ROM data by yourself. Single core simulations are run in parallel in batches with the number of cores set by the `CORES` variable:

```console
CORES=8 make rom
```

The snasphots will be generated at `ITHACAoutput/Offline` with `ITHACAoutput/Parameters` showing the coressponding parameters for every folder in `ITHACAoutput/Offline`. The `ITHACAoutput/Reconstruction` contains folders for the online stage for the selected parameters. All the ROM data wil be collected in the `surrogates` folder.

### Using the ROM

Once that you have the surrogates you can cd into an example and test the `rom.js` module. For example:

```console
cd examples/OpenFOAM/incompressible/simpleFoam/pitzDaily
./run-online.sh
```

## Option 2 Building and testing by natively building the third-party libraries

This option compiles Emscripten versions of Splinter, Eigen and VTK. OpenFOAM and ITHACA-FV are also compiled.

### Requirements

* [Docker](https://www.docker.com/get-started) 20.10.12
* npm 6.14.11
* node v14.15.5

Note: Docker is only used for compiling with Emscripten.

### Building

Initialize the third-party submodules with:

```console
git submodule update --init --recursive
```

A local installation of ITHACA-FV ([@carpemonf fork](https://github.com/carpemonf/ITHACA-FV)) and OpenFOAM (v2106) is needed. You can use your local versions and skip this step and jump to [Generating the ROM data](#generating-the-rom-data-with-native-openfoam-and-ithaca-fv).

Check system [requirements](https://www.openfoam.com/documentation/system-requirements) for OpenFOAM and ITHACA-FV and run:

```console
make native-thirdparty
```

Ported code need to be also compiled before building the final `rom.js` module with:

```console
make native-thirdparty-emcc
```

Install the package dependencies:

```console
make native-install
```

For building the `rom.js` module run:

```console
make native-build
```

### Generating the ROM data with native OpenFOAM and ITHACA-FV

The CFD snapshots are generated directly with OpenFOAM and later used in ITHACA-FV for generating the ROM. This results in hundreds of simulation executions and multiple GB of data. You can skip running this step by directly downloading the ROM data into the `surrogates` folder with:

```console
make native-data
```

Alternatively, You can also create the ROM data by yourself. Single core simulations are run in parallel in batches with the number of cores set by the `CORES` variable:

```console
CORES=8 make native-rom
```

If you have your own installation of ITHACA-FV ([@carpemonf fork](https://github.com/carpemonf/ITHACA-FV)) and OpenFOAM (v2106), just set up the environment and run:

```console
cd examples && ./Allrun 8
```

The snasphots will be generated at `ITHACAoutput/Offline` with `ITHACAoutput/Parameters` showing the coressponding parameters for every folder in `ITHACAoutput/Offline`. The `ITHACAoutput/Reconstruction` contains folders for the online stage for the selected parameters. All the ROM data wil be collected in the `surrogates` folder.

### Using the ROM

Once that you have the surrogates you can cd into an example and test the `rom.js` module. For example:

```console
cd examples/OpenFOAM/incompressible/simpleFoam/pitzDaily
./run-online.sh
```

## Contributing

Everyone is welcome to contribute to this project. See [CONTRIBUTING.md](https://github.com/simzero-oss/rom-js/blob/main/CONTRIBUTING.md) for further details.

Your donations encourage future developments and help with server costs for providing a better service. If you like the tool you can [:heart: donate](https://www.paypal.com/donate/?hosted_button_id=KKB4LH96E59A4).

## Citation

- Article published in the OpenFOAM® Journal:

```
@article{Pena-Monferrer_Diaz-Marin_2022,
  author={Peña-Monferrer, Carlos and Diaz-Marin, Carmen},
  title={rom.js/cfd.xyz: An open-source framework for generating and visualizing parametric {CFD} results},
  journal={OpenFOAM® Journal},
  volume={2},
  month={Oct.},
  pages={143–148}
  DOI={10.51560/ofj.v2.83},
  url={https://journal.openfoam.com/index.php/ofj/article/view/83},
  year={2022},
}
```

- Repository:
```
@online{rom_js_repo_2022,
  author={{SIMZERO}},
  title={{rom.js}},
  howpublished={\url{https://github.com/simzero-oss/rom-js}},
  addendum="(accessed: 28.04.2022)",
}
```

## License

[GNU Lesser General Public License v3.0](https://github.com/simzero-oss/rom-js/blob/main/LICENSE)
