Use Antares for new metrics

If you want to use the Cerfacs pre/post processing suite Antares, here follows a quickstart:

Create a Base from tekigo Solution

You can create an Antares base using the usual readers. To make things easier, here follows a function encapsulating the base creation:

import antares as ant
def base_from_avbp_meshsol(meshname, solname):
    """Build ann AVBP mesh and solution
    
    Args:
        meshname (str): path to the mesh file
        solhname (str): path to the sol file
    
    Returns:
        base : antares base
        """
    r = ant.Reader('hdf_avbp')
    r['filename'] = meshname
    r['shared'] = True
    base = r.read()
    r = ant.Reader('hdf_avbp')
    r['filename'] = solname
    r['base'] = base
    base = r.read()
    return base

You can insert this function in your tekigo code as follows:

import numpy as np
from tekigo import TekigoSolution

tekigo_sol = TekigoSolution(
    mesh='../../GILGAMESH/trapvtx/trappedvtx.mesh.h5',
    solution='combu.init.h5',
    out_dir='./Results')

x = tekigo_sol.load_qoi('/Mesh/coord_x')
y = tekigo_sol.load_qoi('/Mesh/coord_y')
z = tekigo_sol.load_qoi('/Mesh/coord_z')

x0 = 0.1
y0 = 0.1
z0 = 0.0

rad = np.sqrt((x-x0)**2+(y-y0)**2+(z-z0)**2)
my_qoi = np.where(rad<0.01,0.5,1.0)

tekigo_sol.add_field_to_solmesh("my_qoi", my_qoi)
base = base_from_avbp_meshsol(tekigo_sol.init_mesh, tekigo_sol.init_sol)

Note that we create a new quantity of interest my_qoi and add it to the initial solution using .add_field_to_solmesh() before loading. This my_qoi is now part of the loaded Antares base.

Compute a gradient with Antares

The following example is designed to return the magnitude of a gradient. You can however take any treatement and refit the function.

def antares_gradient(base, qoi_name):
    """Build gradient on antares base
    
    Args:
        base : antares base
        qoi_name (str): name of quantity of interest in antares base
    
    Retuens:
        grad_mad (array): the gradient at nodes

    
    ..warning:
        This function is statefull, base will also hold the gradient components.
    """
    myt = ant.Treatment('gradient')
    myt['base'] = base
    myt['coordinates'] = ['x', 'y', 'z']
    myt['variables'] = [qoi_name]
    base = myt.execute()
    # gradients is at cells, move to node variables
    myt2 = ant.Treatment('cell2node')
    myt2['base'] = base
    myt2['variables'] = [
        f'grad_{qoi_name}_x',
        f'grad_{qoi_name}_y',
        f'grad_{qoi_name}_z'
    ]
    myt2.execute()
    
    grad_mag = np.sqrt(
        base[0][0][(f"grad_{qoi_name}_x", "node")]**2+
        base[0][0][(f"grad_{qoi_name}_y", "node")]**2+
        base[0][0][(f"grad_{qoi_name}_z", "node")]**2
        
    )
    return grad_mag

Note that the treatment antares.Treatment("gradient") adds to the base gradients at the cells. The antares.Treatment("cell2node") is needed to get back to the nodes.

Use these two functions

The full script looks like :


tekigo_sol = TekigoSolution(
    mesh='../../GILGAMESH/trapvtx/trappedvtx.mesh.h5',
    solution='combu.init.h5',
    out_dir='./Results')


x = tekigo_sol.load_qoi('/Mesh/coord_x')
y = tekigo_sol.load_qoi('/Mesh/coord_y')
z = tekigo_sol.load_qoi('/Mesh/coord_z')
x0 = 0.1
y0 = 0.105
z0 = 0.0
rad = np.sqrt((x-x0)**2+(y-y0)**2+(z-z0)**2)
my_qoi = np.where(rad<0.01,0.5,1.0)
tekigo_sol.add_field_to_solmesh("my_qoi", my_qoi)

base = base_from_avbp_meshsol(tekigo_sol.init_mesh, tekigo_sol.init_sol)
grad_mag = antares_gradient(base, "my_qoi")

metric_field = np.where(grad_mag>60,0.5, 1)
tekigo_sol.evaluate_metric(metric_field)

The final result looks like:

Tubular exchanger A metric based on the gradient of a quantity