3D Case#

#%% Libraries import
# import HiDeNN library
import sys  
# sys.path.append("../neurom/")
from neurom.HiDeNN_PDE import MeshNN, NeuROM, MeshNN_2D, MeshNN_1D, MeshNN_3D
# Import pre-processing functions
import neurom.src.Pre_processing as pre
# Import torch librairies
import torch
import torch.nn as nn
# Import mechanical functions
from neurom.src.PDE_Library import Strain, Stress,VonMises_plain_strain
# Import Training funcitons
from neurom.src.Training import Training_2_3D_FEM
#Import post processing libraries
import neurom.Post.Plots as Pplot
import time
import os
import torch._dynamo as dynamo
mps_device = torch.device("mps")
from importlib import reload  # Python 3.4+
import tomllib
import numpy as numpy
import argparse

Load configuration file for 3D case

Default_config_file = 'Configurations/config_3D_Cube_w_hole.toml'

with open(Default_config_file, mode="rb") as f:
    config = tomllib.load(f)

Experiment 1#

  • fixed mesh

  • multi-level training

  • optimizers:

    • l-bfgs

    • Adam + l-bfgs

element_size = 1
max_refinment = 5

config["solver"]["FrozenMesh"] = True
config["interpolation"]["MaxElemSize2D"] = element_size
optimizers = ["adam","lbfgs"]

for o in optimizers:
    config["training"]["optimizer"] = o

    for refin in range(1,max_refinment+1):
        config["training"]["multiscl_max_refinment"] = refin

        if config["interpolation"]["dimension"] == 1:
            Mat = pre.Material(         flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["geometry"]["A"]             # Section area of the 1D bar
                                )
        elif config["interpolation"]["dimension"] in [2, 3]:
            try:
                Mat = pre.Material(     flag_lame = False,                              # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["material"]["nu"]            # Poisson's ratio
                                )
            except:
                Mat = pre.Material(     flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["lmbda"],        # First Lame's coef
                                        coef2     = config["material"]["mu"]            # Second Lame's coef
                                )

        MaxElemSize = pre.ElementSize(
                                        dimension     = config["interpolation"]["dimension"],
                                        L             = config["geometry"]["L"],
                                        order         = config["interpolation"]["order"],
                                        np            = config["interpolation"]["np"],
                                        MaxElemSize2D = config["interpolation"]["MaxElemSize2D"]
                                    )
        Excluded = []
        Mesh_object = pre.Mesh( 
                                        config["geometry"]["Name"],                 # Create the mesh object
                                        MaxElemSize, 
                                        config["interpolation"]["order"], 
                                        config["interpolation"]["dimension"]
                                    )
        Mesh_object.AddBorders(config["Borders"]["Borders"])
        Mesh_object.AddBCs(                                                         # Include Boundary physical domains infos (BCs+volume)
                                        config["geometry"]["Volume_element"],
                                        Excluded,
                                        config["DirichletDictionryList"]
                            )                   

        Mesh_object.MeshGeo()                                                       # Mesh the .geo file if .msh does not exist
        Mesh_object.ReadMesh()                                                      # Parse the .msh file
        Mesh_object.ExportMeshVtk()

        if int(Mesh_object.dim) != int(Mesh_object.dimension):
            raise ValueError("The dimension of the provided geometry does not match the job dimension")

        Model_FEM = MeshNN_3D(Mesh_object, n_components = 3)

        Model_FEM.Freeze_Mesh()
        Model_FEM.UnFreeze_FEM()

        if not config["solver"]["FrozenMesh"]:
            Model_FEM.UnFreeze_Mesh() 

        Model_FEM.RefinementParameters( MaxGeneration = config["training"]["h_adapt_MaxGeneration"], 
                                    Jacobian_threshold = config["training"]["h_adapt_J_thrshld"])

        Model_FEM.TrainingParameters(   loss_decrease_c = config["training"]["loss_decrease_c"], 
                                        Max_epochs = config["training"]["n_epochs"], 
                                        learning_rate = config["training"]["learning_rate"])

        Model_FEM.train()                           
        Model_FEM = Training_2_3D_FEM(Model_FEM, config, Mat)

        training_time = Model_FEM.training_recap["Duration_tot"]

        torch.save(Model_FEM.state_dict(), 'Trained_models/Experiment_1/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item()))
        numpy.save('Trained_models/Experiment_1/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item()) +"_time.npy", training_time)

        # Pplot.ExportFinalResult_VTK(Model_FEM,Mat,config["postprocess"]["Name_export"]+"_"+str(Model_FEM.state_dict()["h_max"].item())+"_final_1")
        # Pplot.ExportHistoryResult_VTK(Model_FEM,Mat,config["postprocess"]["Name_export"])

Experiment 2#

  • fixed mesh

  • single-level training

  • optimizers:

    • l-bfgs

    • Adam + l-bfgs

element_sizes = [1, 0.5, 0.25, 0.125, 0.0625]

config["training"]["multiscl_max_refinment"] = 1
config["solver"]["FrozenMesh"] = True
optimizers = ["lbfgs","adam"]

for o in optimizers:
    config["training"]["optimizer"] = o

    for e in element_sizes:
        config["interpolation"]["MaxElemSize2D"] = e

        if config["interpolation"]["dimension"] == 1:
            Mat = pre.Material(         flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["geometry"]["A"]             # Section area of the 1D bar
                                )
        elif config["interpolation"]["dimension"] in [2, 3]:
            try:
                Mat = pre.Material(     flag_lame = False,                              # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["material"]["nu"]            # Poisson's ratio
                                )
            except:
                Mat = pre.Material(     flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["lmbda"],        # First Lame's coef
                                        coef2     = config["material"]["mu"]            # Second Lame's coef
                                )

        MaxElemSize = pre.ElementSize(
                                        dimension     = config["interpolation"]["dimension"],
                                        L             = config["geometry"]["L"],
                                        order         = config["interpolation"]["order"],
                                        np            = config["interpolation"]["np"],
                                        MaxElemSize2D = config["interpolation"]["MaxElemSize2D"]
                                    )
        Excluded = []
        Mesh_object = pre.Mesh( 
                                        config["geometry"]["Name"],                 # Create the mesh object
                                        MaxElemSize, 
                                        config["interpolation"]["order"], 
                                        config["interpolation"]["dimension"]
                                    )
        Mesh_object.AddBorders(config["Borders"]["Borders"])
        Mesh_object.AddBCs(                                                         # Include Boundary physical domains infos (BCs+volume)
                                        config["geometry"]["Volume_element"],
                                        Excluded,
                                        config["DirichletDictionryList"]
                            )                   

        Mesh_object.MeshGeo()                                                       # Mesh the .geo file if .msh does not exist
        Mesh_object.ReadMesh()                                                      # Parse the .msh file
        Mesh_object.ExportMeshVtk()

        if int(Mesh_object.dim) != int(Mesh_object.dimension):
            raise ValueError("The dimension of the provided geometry does not match the job dimension")

        Model_FEM = MeshNN_3D(Mesh_object, n_components = 3)

        Model_FEM.Freeze_Mesh()
        Model_FEM.UnFreeze_FEM()

        if not config["solver"]["FrozenMesh"]:
            Model_FEM.UnFreeze_Mesh() 

        Model_FEM.RefinementParameters( MaxGeneration = config["training"]["h_adapt_MaxGeneration"], 
                                    Jacobian_threshold = config["training"]["h_adapt_J_thrshld"])

        Model_FEM.TrainingParameters(   loss_decrease_c = config["training"]["loss_decrease_c"], 
                                        Max_epochs = config["training"]["n_epochs"], 
                                        learning_rate = config["training"]["learning_rate"])

        Model_FEM.train()                           
        Model_FEM = Training_2_3D_FEM(Model_FEM, config, Mat)

        training_time = Model_FEM.training_recap["Duration_tot"]

        torch.save(Model_FEM.state_dict(), 'Trained_models/Experiment_2/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item())) # To save a full coarse model
        numpy.save('Trained_models/Experiment_2/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item()) +"_time.npy", training_time)
        
        # Pplot.ExportFinalResult_VTK(Model_FEM,Mat,config["postprocess"]["Name_export"]+"_"+str(Model_FEM.state_dict()["h_max"].item())+"_final_2")

Experiment 3#

  • single-level training

  • r-adaptive mesh

  • optimizers:

    • l-bfgs

    • Adam + l-bfgs

# Experiment
element_sizes = [1, 0.5, 0.25]

config["training"]["multiscl_max_refinment"] = 1
config["solver"]["FrozenMesh"] = False
optimizers = ["lbfgs","adam"]

for o in optimizers:
    config["training"]["optimizer"] = o

    for e in element_sizes:
        config["interpolation"]["MaxElemSize2D"] = e

        if config["interpolation"]["dimension"] == 1:
            Mat = pre.Material(         flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["geometry"]["A"]             # Section area of the 1D bar
                                )
        elif config["interpolation"]["dimension"] in [2, 3]:
            try:
                Mat = pre.Material(     flag_lame = False,                              # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["material"]["nu"]            # Poisson's ratio
                                )
            except:
                Mat = pre.Material(     flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["lmbda"],        # First Lame's coef
                                        coef2     = config["material"]["mu"]            # Second Lame's coef
                                )

        MaxElemSize = pre.ElementSize(
                                        dimension     = config["interpolation"]["dimension"],
                                        L             = config["geometry"]["L"],
                                        order         = config["interpolation"]["order"],
                                        np            = config["interpolation"]["np"],
                                        MaxElemSize2D = config["interpolation"]["MaxElemSize2D"]
                                    )
        Excluded = []
        Mesh_object = pre.Mesh( 
                                        config["geometry"]["Name"],                 # Create the mesh object
                                        MaxElemSize, 
                                        config["interpolation"]["order"], 
                                        config["interpolation"]["dimension"]
                                    )
        Mesh_object.AddBorders(config["Borders"]["Borders"])
        Mesh_object.AddBCs(                                                         # Include Boundary physical domains infos (BCs+volume)
                                        config["geometry"]["Volume_element"],
                                        Excluded,
                                        config["DirichletDictionryList"]
                            )                   

        Mesh_object.MeshGeo()                                                       # Mesh the .geo file if .msh does not exist
        Mesh_object.ReadMesh()                                                      # Parse the .msh file
        Mesh_object.ExportMeshVtk()

        if int(Mesh_object.dim) != int(Mesh_object.dimension):
            raise ValueError("The dimension of the provided geometry does not match the job dimension")

        Model_FEM = MeshNN_3D(Mesh_object, n_components = 3)

        Model_FEM.Freeze_Mesh()
        Model_FEM.UnFreeze_FEM()

        if not config["solver"]["FrozenMesh"]:
            Model_FEM.UnFreeze_Mesh() 


        Model_FEM.RefinementParameters( MaxGeneration = config["training"]["h_adapt_MaxGeneration"], 
                                    Jacobian_threshold = config["training"]["h_adapt_J_thrshld"])

        Model_FEM.TrainingParameters(   loss_decrease_c = config["training"]["loss_decrease_c"], 
                                        Max_epochs = config["training"]["n_epochs"], 
                                        learning_rate = config["training"]["learning_rate"])

        Model_FEM.train()                           
        Model_FEM = Training_2_3D_FEM(Model_FEM, config, Mat)

        training_time = Model_FEM.training_recap["Duration_tot"]

        torch.save(Model_FEM.state_dict(), 'Trained_models/Experiment_3/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item())) # To save a full coarse model
        Pplot.ExportFinalResult_VTK(Model_FEM,Mat,config["postprocess"]["Name_export"]+"_"+str(Model_FEM.state_dict()["h_max"].item())+"_final_3")
        numpy.save('Trained_models/Experiment_3/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item()) +"_time.npy", training_time)

Experiment 4#

  • r-adaptive mesh in the last level only

  • multi-level training

  • optimizers:

    • l-bfgs

    • Adam + l-bfgs

# Experiment
element_size = 1
max_refinment = 3

config["solver"]["FrozenMesh"] = True
config["solver"]["UnfreezeFinal"] = True
config["interpolation"]["MaxElemSize2D"] = element_size
optimizers = ["lbfgs","adam"]

for o in optimizers:
    config["training"]["optimizer"] = o

    for refin in range(1,max_refinment+1):
        config["training"]["multiscl_max_refinment"] = refin

        if config["interpolation"]["dimension"] == 1:
            Mat = pre.Material(         flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["geometry"]["A"]             # Section area of the 1D bar
                                )
        elif config["interpolation"]["dimension"] in [2, 3]:
            try:
                Mat = pre.Material(     flag_lame = False,                              # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["E"],            # Young Modulus
                                        coef2     = config["material"]["nu"]            # Poisson's ratio
                                )
            except:
                Mat = pre.Material(     flag_lame = True,                               # If True should input lmbda and mu instead of E and nu
                                        coef1     = config["material"]["lmbda"],        # First Lame's coef
                                        coef2     = config["material"]["mu"]            # Second Lame's coef
                                )

        MaxElemSize = pre.ElementSize(
                                        dimension     = config["interpolation"]["dimension"],
                                        L             = config["geometry"]["L"],
                                        order         = config["interpolation"]["order"],
                                        np            = config["interpolation"]["np"],
                                        MaxElemSize2D = config["interpolation"]["MaxElemSize2D"]
                                    )
        Excluded = []
        Mesh_object = pre.Mesh( 
                                        config["geometry"]["Name"],                 # Create the mesh object
                                        MaxElemSize, 
                                        config["interpolation"]["order"], 
                                        config["interpolation"]["dimension"]
                                    )
        Mesh_object.AddBorders(config["Borders"]["Borders"])
        Mesh_object.AddBCs(                                                         # Include Boundary physical domains infos (BCs+volume)
                                        config["geometry"]["Volume_element"],
                                        Excluded,
                                        config["DirichletDictionryList"]
                            )                   

        Mesh_object.MeshGeo()                                                       # Mesh the .geo file if .msh does not exist
        Mesh_object.ReadMesh()                                                      # Parse the .msh file
        Mesh_object.ExportMeshVtk()

        if int(Mesh_object.dim) != int(Mesh_object.dimension):
            raise ValueError("The dimension of the provided geometry does not match the job dimension")

        Model_FEM = MeshNN_3D(Mesh_object, n_components = 3)

        Model_FEM.Freeze_Mesh()
        Model_FEM.UnFreeze_FEM()

        if config["solver"]["UnfreezeFinal"] and config["training"]["multiscl_max_refinment"]==1:
            Model_FEM.UnFreeze_Mesh() 

        if not config["solver"]["FrozenMesh"]:
            Model_FEM.UnFreeze_Mesh() 

        Model_FEM.RefinementParameters( MaxGeneration = config["training"]["h_adapt_MaxGeneration"], 
                                    Jacobian_threshold = config["training"]["h_adapt_J_thrshld"])

        Model_FEM.TrainingParameters(   loss_decrease_c = config["training"]["loss_decrease_c"], 
                                        Max_epochs = config["training"]["n_epochs"], 
                                        learning_rate = config["training"]["learning_rate"])

        Model_FEM.train()                           
        Model_FEM = Training_2_3D_FEM(Model_FEM, config, Mat)

        training_time = Model_FEM.training_recap["Duration_tot"]

        torch.save(Model_FEM.state_dict(), 'Trained_models/Experiment_4/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item())) # To save a full coarse model
        Pplot.ExportFinalResult_VTK(Model_FEM,Mat,config["postprocess"]["Name_export"]+"_"+str(Model_FEM.state_dict()["h_max"].item())+"_final_4")
        numpy.save('Trained_models/Experiment_4/'+o+'_3D_Cube_'+ str(Model_FEM.state_dict()["h_max"].item()) +"_time.npy", training_time)

Save & Load model#