Source code for Muscat.MeshTools.RemeshBackEnds.MmgRemeshing

# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#

from typing import Union, Optional
from pathlib import Path
from Muscat.IO.MeshWriter import WriteMesh
from Muscat.IO.MeshReader import ReadMesh
from Muscat.MeshContainers.Mesh import Mesh
from Muscat.Helpers.IO.Which import Which
from Muscat.Helpers.IO.TemporaryDirectory import TemporaryDirectory
from Muscat.MeshTools.Remesh import RegisterRemesherClass

[docs] class MmgRemeshing(): def __init__(self, mesh: Mesh, solution = None, levelset=None, metric = None): self.mesh = mesh if levelset is not None: raise RuntimeError(' MmgRemeshing does not support the argument levelset') self.solution = solution self.metric = metric self.temp_out_path = None def __WriteMeshAndSolution(self, temp_path: Union[str, Path] = None, binary: bool = True): """Write mesh and solution in a mesh file Parameters ---------- temp_path : Union[str,Path] path of the output mesh file (without extension) binary : bool """ from Muscat.MeshTools.MeshTools import TagsToRefs if temp_path is None: temp_path = Path("temp_file") solutionOnOwnFile = True self.temp_mesh_path = Path(str(temp_path)+".mesh"+binary*"b") self.temp_sol_path = Path(str(temp_path)+".sol"+binary*"b") if not self.temp_out_path: self.temp_out_path = Path(str(temp_path)+".o.mesh"+binary*"b") if self.solution is not None: solution = [self.solution] elif self.metric is not None: solution = [self.metric] else: solution = None solutionOnOwnFile = False RefByNode, self.dictNodesRefsToTags, RefByElement, self.dictElemRefsToTags = TagsToRefs(self.mesh) WriteMesh(str(self.temp_mesh_path), self.mesh, PointFields = solution, solutionOnOwnFile = solutionOnOwnFile, binary = binary, nodalRefNumber = RefByNode, elemRefNumber = RefByElement) def __BuildMmgCommandLine(self, backEndOptions: dict): """Build command line for mmg execution Parameters ---------- options : dict keys corresponding to mmg option name and value corresponding to value if applicable Returns ------- CommandLine : str the command line for mmg execution """ CommandLine = [] isElem3d = self.mesh.GetNumberOfElements(dim = 3) > 0 if isElem3d: CommandLine.append(Which("mmg3d_O3")) else: if self.mesh.GetPointsDimensionality() == 3: CommandLine.append(Which("mmgs_O3")) else: CommandLine.append(Which("mmg2d_O3")) CommandLine.append("-in") CommandLine.append(str(self.temp_mesh_path)) if self.solution is not None: CommandLine.append("-sol") CommandLine.append(str(self.temp_sol_path)) elif self.metric is not None: CommandLine.append("-met") CommandLine.append(str(self.temp_sol_path)) for key, value in backEndOptions.items(): CommandLine.append("-"+key) if value: CommandLine.append(str(value)) return " ".join(CommandLine) def __LaunchMmg(self, CommandLine:str): """Launch mmg with a subprocess using command line Parameters ---------- CommandLine : str the command line for mmg execution """ import subprocess return subprocess.check_output(CommandLine, shell = True).decode("utf-8", errors = "ignore") def __ReadMesh(self, prefix = "mmg"): """Read mesh file produced by mmg Returns ------- mesh : Mesh mmg resulting mesh from adaption """ from Muscat.MeshTools.MeshTools import RefsToTags mesh = ReadMesh(str(self.temp_out_path), ReadRefsAsField = True) mesh = RefsToTags(mesh, self.dictNodesRefsToTags, self.dictElemRefsToTags, prefix) return mesh
[docs] def Runner(self, remesher_options:dict, backEndOptions:dict): """Run the process to write mesh in an inria mesh file, launch mmg and read the resulting mesh Notes ----- The inria mesh file (called `temp_name`) will be writen in a temporary directory Parameters ---------- remesher_options : dict keys corresponding to mmg option name and value corresponding to value if applicable backEndOptions: dict Extra option for the "by file" mmg communication "temp_name" : str name of the output mesh file (without extension) default : "temp_file" "binary" : bool defaults to `True` "prefix" : str defaults to "mmg" "keep_temp_files" : bool defaults to `False` "temp_dir" : str directory to store temporary files if none a Temporary Directory is used for temporary file, default None Returns ------- mesh : Mesh mmg resulting mesh from adaption """ if remesher_options is None: remesher_options = {} if backEndOptions is None: backEndOptions = {} temp_name = backEndOptions.get("temp_name", "temp_file") binary = backEndOptions.get("binary", True) prefix = backEndOptions.get("prefix", "mmg") keep_temp_files = backEndOptions.get("keep_temp_files", False) temp_dir = backEndOptions.get("temp_dir", None) print_logtime = backEndOptions.get("logtime", True) out_name = remesher_options.get("out", None) if out_name: self.temp_out_path = Path(out_name+".mesh"+binary*"b") if not temp_dir: temp_dir = Path(TemporaryDirectory.GetTempPath()) temp_path = Path(temp_dir) / Path(temp_name) self.__WriteMeshAndSolution(temp_path, binary) CommandLine = self.__BuildMmgCommandLine(remesher_options) mmg_out = self.__LaunchMmg(CommandLine) if print_logtime: print(mmg_out.split("\n")[-2].split(" ")[-1]) mesh = self.__ReadMesh(prefix) if not(keep_temp_files): self.temp_mesh_path.unlink(missing_ok=True) self.temp_sol_path.unlink(missing_ok=True) self.temp_out_path.unlink(missing_ok=True) return mesh
RegisterRemesherClass("MmgByFiles", MmgRemeshing) RegisterRemesherClass("MmgByFile", MmgRemeshing)
[docs] def CheckIntegrity(GUI=False): import time import numpy as np from Muscat.IO.GmshReader import ReadGmsh from Muscat.TestData import GetTestDataPath from Muscat.Helpers.IO.TemporaryDirectory import TemporaryDirectory tic = time.time() mmgExec = Which("mmg3d_O3") if mmgExec == '' or mmgExec is None: return "skip" print("Reading mesh") filename = GetTestDataPath()+"dent3D.msh" mesh = ReadGmsh(filename) mesh.ConvertDataForNativeTreatment() print(mesh) print("Execution time:", int(time.time()-tic), "seconds") tic = time.time() print("Executing mmg3d") obj = MmgRemeshing(mesh=mesh, solution=None) mesh = obj.Runner({"hmin": 0.1}, backEndOptions={"binary": False}) obj = MmgRemeshing(mesh=mesh, solution=None) mesh = obj.Runner({"hmin": 0.1}, backEndOptions={"binary": False, "temp_name": "test_mmg"}) obj = MmgRemeshing(mesh=mesh, solution=None) mesh = obj.Runner({"hmin": 0.1}, backEndOptions={"binary": False, "temp_name": "test_mmg", "temp_dir": TemporaryDirectory.GetTempPath()}) obj = MmgRemeshing(mesh=mesh, solution=None) mesh = obj.Runner({"hmin": 0.1}, backEndOptions={"binary": False, "temp_dir": TemporaryDirectory.GetTempPath()}) obj = MmgRemeshing(mesh=mesh, solution=np.ones(mesh.GetNumberOfNodes())) mesh = obj.Runner({"hmin": 0.1}, backEndOptions={"binary": True}) obj = MmgRemeshing(mesh=mesh, solution=np.ones(mesh.GetNumberOfNodes())) mesh = obj.Runner({"hmin": 0.1, "out": f"{TemporaryDirectory.GetTempPath()}/adapted_mesh"}, backEndOptions={"binary": True}) print(mesh) print("Execution time:", int(time.time()-tic), "seconds") return "ok"
if __name__ == '__main__': print(CheckIntegrity())