Offline Phase: SGREEDY algorithm for sensor placement

This notebook implements the following algorithm for sensor placement:

  • Stabilised GREEDY algorithm (SGREEDY)

[1]:
import numpy as np
import os
from IPython.display import clear_output
import pickle

import gmsh
from mpi4py import MPI
from dolfinx.io.gmshio import model_to_mesh
from dolfinx.fem import FunctionSpace

from pyforce.tools.write_read import ImportH5, StoreFunctionsList as store
from pyforce.tools.functions_list import FunctionsList
from pyforce.offline.sensors import SGREEDY

path_off ='./Offline_results/'

The geometry is imported from “ANL11A2_octave.geo”, generated with GMSH. Then, the mesh is created with the gmsh module.

[2]:
gdim = 2

model_rank = 0
mesh_comm = MPI.COMM_WORLD

# Initialize the gmsh module
gmsh.initialize()

# Load the .geo file
gmsh.merge('ANL11A2_octave.geo')
gmsh.model.geo.synchronize()

# Set algorithm (adaptive = 1, Frontal-Delaunay = 6)
gmsh.option.setNumber("Mesh.Algorithm", 6)

gmsh.model.mesh.generate(gdim)
gmsh.model.mesh.optimize("Netgen")

# Domain
domain, ct, ft = model_to_mesh(gmsh.model, comm = mesh_comm, rank = model_rank, gdim = gdim )
gmsh.finalize()

fuel1_marker    = 1
fuel2_marker    = 2
fuel_rod_marker = 3
refl_marker     = 4

void_marker     = 10
sym_marker      = 20

tdim = domain.topology.dim
fdim = tdim - 1
domain.topology.create_connectivity(fdim, tdim)

clear_output()

Importing Snapshots

The snapshots are loaded and stored into suitable data structures.

[3]:
# Defining the functional space
V = FunctionSpace(domain, ("Lagrange", 1))

# Define the variables to load
var_names = [
             'phi_1',
             'phi_2'
             ]

tex_var_names = [
                 r'\phi_1',
                 r'\phi_2'
                 ]

# Snapshot path
path_FOM = './Snapshots/'

################ Importing Snapshots ########################
test_snaps = list()

for field_i in range(len(var_names)):
    test_snaps.append(FunctionsList(V))

    tmp_FOM_list, _ = ImportH5(V, path_FOM+'test_snap_'+var_names[field_i], var_names[field_i])

    for mu in range(len(tmp_FOM_list)):
        test_snaps[field_i].append(tmp_FOM_list(mu))

    del tmp_FOM_list

test_params = list()
for field_i in range(len(var_names)):
    with open(path_FOM+'./test.param', 'rb') as f:
        test_params.append(pickle.load(f))

Let us import the POD modes

[4]:
bf = dict()

for field_i in range(len(var_names)):

    bf[var_names[field_i]] = ImportH5(V, path_off+'/BasisFunctions/basisPOD_'+var_names[field_i], 'POD_'+var_names[field_i])[0]

SGREEDY for POD basis

A greedy procedure is set up to maximise the inf-sup constant \(\beta_{N,M}\), for 3 different values if the point spread

[5]:
s = [0.1, 1., 2.5]
sgreedy_pod = dict()

for field_i in range(len(var_names)):
    sgreedy_pod[var_names[field_i]] = [SGREEDY(domain, bf[var_names[field_i]], V, var_names[field_i], s_jj) for s_jj in s]

Since the snapshots belong to \(H^1\subset L^2\), the Riesz representation of a functional is sought in this space, endowed with the inner product \begin{equation*} \left(u,v\right)_{H^1}=\int_\Omega \nabla u\cdot \nabla v\,d\Omega + \int_\Omega u\cdot v\,d\Omega \end{equation*} The results will be compared with the approximation properties of the case with the Riesz representation in \(L^2\), whose inner product is \begin{equation*} \left(u,v\right)_{L^2} = \int_\Omega u\cdot v\,d\Omega \end{equation*}

[6]:
Nmax = 10
Mmax = 30

sam_every = 2

is_H1 = [False, True]
fun_space_label = ['L2', 'H1']

for field_i in range(len(var_names)):
    for jj in range(len(s)):
        for kk in range(len(is_H1)):

            print('SGREEDY for '+var_names[field_i]+' with s={:.2f}'.format(s[jj])+' and Riesz representation in '+fun_space_label[kk])

            sgreedy_pod[var_names[field_i]][jj].generate(Nmax, Mmax, tol = 0.5, sampleEvery = sam_every, verbose=False, is_H1 = is_H1[kk])
            store(domain, sgreedy_pod[var_names[field_i]][jj].basis_sens,
                  'SGREEDYPOD_' +var_names[field_i]+'_s_{:.2e}'.format(s[jj]),
                  path_off+'/BasisSensors/sensorsSGREEDYPOD_' + var_names[field_i]+'_s_{:.2e}_'.format(s[jj])+fun_space_label[kk])
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.002 s/it
m = 30, n = 10 | beta_n,m = 0.084779
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.003 s/it
m = 30, n = 10 | beta_n,m = 0.146526
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.002 s/it
m = 30, n = 10 | beta_n,m = 0.180025
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.003 s/it
m = 30, n = 10 | beta_n,m = 0.223101
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.002 s/it
m = 30, n = 10 | beta_n,m = 0.393625
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.003 s/it
m = 30, n = 10 | beta_n,m = 0.398683
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.002 s/it
m = 30, n = 10 | beta_n,m = 0.085134
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.003 s/it
m = 30, n = 10 | beta_n,m = 0.148458
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.002 s/it
m = 30, n = 10 | beta_n,m = 0.173819
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.003 s/it
m = 30, n = 10 | beta_n,m = 0.214982
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.002 s/it
m = 30, n = 10 | beta_n,m = 0.357794
Generating sensors (sampled every 2 cells): 3435.000 / 3435.00 - 0.003 s/it
m = 30, n = 10 | beta_n,m = 0.371680