# 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
```

Alternatively, the module 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 usage example can be found in `examples examples/OpenFOAM/incompressible/simpleFoam/pitzDaily`. The `Allrun` script will run the simulations and generate the ROM. The `rom.js` can be then used as shown below for `node.js` (full code at `applications/steady/online`):

```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(Nphi_u + Nphi_p, Nphi_u + Nphi_p);

  // - Setting up grid and ROM data
  reduced.stabilization(argv.stabilization);
  reduced.readUnstructuredGrid(grid_data);
  reduced.Nphi_u(Nphi_u);
  reduced.Nphi_p(Nphi_p);
  reduced.Nphi_nut(Nphi_nut);
  reduced.N_BC(N_BC);
  reduced.addMatrices(P[0], K[0], B[0]);
  reduced.addModes(modes);
  reduced.setRBF(mu, coeffL2);

  // - Loading turbulent related matrices and weights
  for (var i = 0; i < Nphi_u; i ++ ){
    const C = await loadData("matrices/C" + i + "_mat.txt");
    const Ct1 = await loadData("matrices/ct1_" + i + "_mat.txt");
    const Ct2 = await loadData("matrices/ct2_" + i + "_mat.txt");

    reduced.addCMatrix(C[0], i);
    reduced.addCt1Matrix(Ct1[0], i);
    reduced.addCt2Matrix(Ct2[0], i);
  }

  for (var i = 0; i < Nphi_nut; i ++ ){
    const weight = await loadData('wRBF_' + i + '_mat.txt');
    reduced.addWeight(weight[0], i);
  }

  reduced.preprocess();

  // - 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 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

A technical note related to this work was submitted to the OpenFOAM Journal and it is currently being reviewed. In the meanwhile please use the following bibtex to cite this repository:

- Technical note submitted to the OpenFOAM Journal and under review. Preprint available at arXiv:

```
@misc{cfd_xyz_note_2022,
  doi = {10.48550/ARXIV.2205.08387},
  url = {https://arxiv.org/abs/2205.08387},
  author = {Peña-Monferrer, Carlos and Díaz-Marín, Carmen},
  keywords = {Fluid Dynamics (physics.flu-dyn), Numerical Analysis (math.NA), FOS: Physical sciences, FOS: Physical sciences, FOS: Mathematics, FOS: Mathematics},
  title = {cfd.xyz/rom.js: An open-source framework for generating and visualizing parametric CFD results on the web},
  publisher = {arXiv},
  year = {2022},
  copyright = {Creative Commons Attribution Share Alike 4.0 International}
}
```

- 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)
