# kalast

[![logo image]][doc link]

[![crate badge]][crate link]
[![doc badge]][doc link]
[![license badge]][license link]
[![pre-commit badge]][pre-commit link]

> Thermophysical model for binary systems of asteroids

---

[Demo](#demo) |
[In Action](#in-action) |
[Installation](#installation) |
[License](#license)

---

## Demo

[![asciicast image]][asciicast link]

## In action

Computation of the temperature of a single point at the surface of an asteroid (initialized as sub-solar-point):

```rust
// src/main.rs

use kalast::{
    EnvironmentSystem, Properties, SingleBody, Time, World, ASTRONAUMICAL_UNIT, HOUR, M3, MINUTE,
    V3,
};

fn main() {
    // [OPTIONAL] To enable log information.
    kalast::log_init!();

    // Define an empty object.
    let mut asteroid = SingleBody::empty_object(
        "Dimorphos",                                          // name
        -V3::new(1.0, 0.0, 0.0) * ASTRONAUMICAL_UNIT * 1.074, // position ICRS Sun-centered
        Properties::new(
            11.92 * HOUR, // rotation period
            11.92 * HOUR, // revolution period
            0.,           // obliquity
            500.0,        // thermal inertia
            2146.0,       // density
            600.0,        // heat capacity
            0.07,         // albedo
            0.9,          // emissivity
        ),
    );

    // Add a single facet at longitude = latitude = 0° of 2m² surface area.
    asteroid.body_mut().new_face(&M3::from_column_slice(&[
        1.0,       // vertex 1 x
        -2. / 3.,  //          y
        2. / 3.,   //          z
        1.0,       // vertex 2 x
        -2.0 / 3., //          y
        -4. / 3.,  //          z
        1.0,       // vertex 3 x
        4. / 3.,   //          y
        2. / 3.,   //          z
    ]));
    // Complete model = false ==>> no mutual nor self heating.
    asteroid.complete_model(false);

    // Time
    let time = Time::new(
        10.0 * asteroid.body().properties.revolution_period(), // duration
        10.0 * MINUTE,                                         // time step
    );

    // Initialize the World.
    let mut world = World::new(time, asteroid);
    // Run the simulation (time loop here).
    world.start();
    // To save the daily temperature in text file.
    world.save_daily("rsc/data/tmp.txt");

    // Some prints to know the temperature at the surface and deepest temperature.
    // Taking at index=0 because there is only one face.
    println!(
        "min: {:.2}, max: {:.2}",
        world.environment_system.body().surface_temperatures()[0],
        world.environment_system.body().deepest_temperatures()[0]
    );

    // Convert ground vector and ground temperatures as slice for plotting.
    let ground = world
        .environment_system
        .body()
        .properties
        .ground_vector()
        .as_slice();
    let temperatures = world
        .environment_system
        .body()
        .ground_temperatures()
        .as_slice();

    // Initialize the graph.
    let graph = kalast::Graph::new(1, 1);
    // Tweaking the graph.
    graph.set_title("Daily ground temperatures");
    graph.set_xlabel(0, "Depth [m]");
    graph.set_ylabel(0, "Temperature [K]");
    graph.set_axis_limits(0, Some(0.), Some(1.1), Some(260.), Some(360.));
    graph.set_legend_title(0, "Hour angle [deg]");
    // Plot ground temperature VS ground depth.
    graph.plot(
        0,
        kalast::args!(graph.py(), ground, temperatures),
        kalast::kwargs!(graph.py(), ("label", "0")),
    );
    // Finalize the graph.
    graph.save("rsc/img/tmp.svg", None);
    graph.show(true);
}

```

## Installation

Get [Rust][rust install]:

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

Create a new Rust project:

```bash
# Move to the directory of your choice and create a project
cargo new my_project

# Move inside your project
cd my_project
```

Add the dependency **kalast** to your `Cargo.toml`:

```toml
...
[dependencies]
kalast = "0.1.9"
```

To get a working code:

+ copy to your `src/main.rs` either the code [above](#in-action) or one from the [examples](examples)
+ get the necessary 3D object [files](rsc/obj)
+ make sure the paths to your 3D file are correct
+ build and run your `src/main.rs` from the root of your project with:

```bash
cargo run --release
```

## If you clone this repo

To build and run the program, tests or examples:

```bash
Usage: ./compile.sh [OPTIONS]
    -r, --release        build in release, default is debug
    -e, --example [NAME] run the example [NAME]
    -t, --test           launch fast tests
    --all-targets        to be used with -t, runs all tests
```

You can also change the environment variable `CUSTOM_RUSTFLAGS` inside the script to customize
compilation options (such as ignoring `dead_code`).

Some examples:

```bash
# To build in debug mode
./compile.sh

# To build in release mode
./compile.sh -r

# To build in release mode the example with two spheres
./compile.sh -re spheres_mutual.rs

# To launch all the tests
./compile.sh -t --all-targets
```

## License

Licensed under the [Apache License, Version 2.0][license link].

[logo image]: https://gitlab-as.oma.be/gregoireh/kalast/-/raw/main/rsc/img/SBMT-dimorphos.png
[crate link]: https://crates.io/crates/kalast
[crate badge]: https://meritbadge.herokuapp.com/kalast?style=flat-square
[doc link]: https://docs.rs/kalast
[doc badge]: https://docs.rs/kalast/badge.svg
[license link]: LICENSE
[license badge]: https://img.shields.io/badge/License-Apache%202.0-blue.svg
[pre-commit link]: https://pre-commit.com
[pre-commit badge]: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white
[asciicast image]: rsc/cast/demo-logo.png
[asciicast link]: https://asciinema.org/a/385357?autoplay=1&speed=5&loop=1&cols=79
[rust install]: https://www.rust-lang.org/learn/get-started
