Source code for OpenPisco.ExternalTools.FreeFem.FreeFemInterface
# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE', which is part of this source code package.
#
"""FreefemInterface
This is the dedicated interface for the external physical solver Code\_Aster.
Its main responsability is to facilitate the interactions with Code\_Aster, either by providing features to build the command line required to run the solver or to retrieve field computed by said solver.
"""
import numpy as np
import os
import shutil
from OpenPisco.ExternalTools.FreeFem import GetScriptsPath as GetScriptsPath
from OpenPisco.Unstructured.AppExecutableTools import AppExecutableBase, CommandLineBuilder
import OpenPisco.PhysicalSolvers.FieldsNames as FN
import OpenPisco.Unstructured.MetricFieldsNames as MFN
#outputs that the solver can generate
FileNamebyFieldName={}
FileNamebyFieldName[FN.potential_energy]="freefeminput.elasticenergy.sol"
FileNamebyFieldName[FN.von_mises]="freefeminput.vonmises.sol"
FileNamebyFieldName[FN.stress]="freefeminput.stress.sol"
FileNamebyFieldName[MFN.metric]="mshmetdata.sol"
FileNamebyScalarName={}
FileNamebyScalarName[FN.int_potential_energy]="intelasticenergy.txt"
freefemExec = "FreeFem++"
[docs]class FreeFemInterface(AppExecutableBase):
"""
.. py:class:: FreeFemInterface
Interface for the finite element solver Freefem++
"""
def __init__(self):
super(FreeFemInterface, self).__init__(freefemExec)
[docs] def DeleteGeneratedFiles(self):
"""Delete specific generated files after run"""
filesToDelete = ["freefeminput.depl.sol","freefeminput.sol"]
self.DeleteFiles(filesToDelete)
[docs] def ExecuteFreefem(self):
"""Run Freefem++ executable"""
source = GetScriptsPath()
assert len(self.filename),"No freefem filename given"
filesFound = [f for f in os.listdir(source) if f.startswith(self.filename)]
assert len(filesFound)<=1,"Ambiguity: Only one file at most should match "+self.filename
if len(filesFound)==1:
freefemFile=filesFound[0]
shutil.copy(os.path.join(source,freefemFile), self.workingDirectory )
cmdBuilder = CommandLineBuilder(self.GetAppName())
cmdBuilder.optionAdd("nw")
cmdBuilder.argumentAdd(self._fileName(self.filename))
cmd = cmdBuilder.result()
self._runCommand(cmd)
[docs] def GetSolution(self, i:int=0)->np.ndarray:
"""Retrieve solution
Parameters
----------
i : int, optional
solution index, by default 0
Returns
-------
np.ndarray
solution at index i
"""
self.fileoutname = self._filePath("freefeminput.depl.sol")
self.reader.SetFileName(self.fileoutname)
res = self.reader.Read()
return res.nodeFields["SolAtVertices"+str(i)]
[docs] def GetNodalField(self,name:str)->np.ndarray:
"""Retrieve nodal field
Parameters
----------
name : str
field name
Returns
-------
np.ndarray
nodal field value
"""
self.fileoutname = self._filePath(FileNamebyFieldName[name])
self.reader.SetFileName(self.fileoutname)
res = self.reader.Read()
if name == FN.stress:
np.hstack((res.nodeFields["SolAtVertices0"], res.nodeFields["SolAtVertices1"]))
if name=='metric' and "SolAtVertices1" in res.nodeFields and "SolAtVertices2" in res.nodeFields:
return np.vstack([res.nodeFields["SolAtVertices0"][:,0],res.nodeFields["SolAtVertices1"][:,0],res.nodeFields["SolAtVertices2"][:,0]]).T
return res.nodeFields["SolAtVertices0"][:,0]
[docs] def GetScalar(self,name:str)->float:
"""Retrieve scalar
Parameters
----------
name : str
scalar name
Returns
-------
float
scalar value
"""
return float(np.loadtxt(self._filePath(FileNamebyScalarName[name])))