Skip to content
Snippets Groups Projects
Commit 01a8267e authored by imcovangent's avatar imcovangent
Browse files

Added functionalities to SSBJ.

Former-commit-id: 25efca8c43f09119795b9ca16e16f3c840819e59
parent 86e998c9
No related branches found
No related tags found
No related merge requests found
......@@ -10,6 +10,8 @@ The files were adjusted for optimal use in KADMOS by Imco van Gent.
from __future__ import absolute_import, division, print_function
import sys
import os
import inspect
import numpy as np
from lxml import etree
......@@ -17,11 +19,16 @@ from lxml import etree
from examples.knowledgebases.ssbj import root_tag, x_tc, x_AR, x_Lambda, x_Sref, x_L, x_WT, x_h, x_M, x_ESF, x_Theta, \
x_CDmin, x_D, x_fin, x_dpdx, x_Cf
from examples.knowledgebases.ssbj.common import PolynomialFunction, add_discipline_to_cmdows, run_tool
from openlego.api import AbstractDiscipline
from openlego.utils.xml_utils import xml_safe_create_element
from kadmos.utilities.xmls import xml_safe_create_element
class Aerodynamics(AbstractDiscipline):
class Aerodynamics(): # AbstractDiscipline
@property
def name(self):
# type: () -> str
""":obj:`str`: Name of this discipline."""
return self.__class__.__name__
@property
def creator(self):
......@@ -39,6 +46,24 @@ class Aerodynamics(AbstractDiscipline):
def description(self):
return u'Aerodynamic analysis discipline of the SSBJ test case.'
@property
def path(self):
# type: () -> str
""":obj:`str`: Path at which this discipline resides."""
return os.path.dirname(inspect.getfile(self.__class__))
@property
def in_file(self):
# type: () -> str
""":obj:`str`: Path of the template input XML file of this discipline."""
return os.path.join(self.path, self.name + '-input.xml')
@property
def out_file(self):
# type: () -> str
""":obj:`str`: Path of the template output XML file of this discipline."""
return os.path.join(self.path, self.name + '-output.xml')
def generate_input_xml(self):
root = etree.Element(root_tag)
doc = etree.ElementTree(root)
......
......@@ -17,7 +17,7 @@ from lxml import etree
from examples.knowledgebases.ssbj import root_tag, x_WT, x_h, x_M, x_fin, x_SFC, x_WF, x_R
from examples.knowledgebases.ssbj.common import add_discipline_to_cmdows, run_tool
from openlego.api import AbstractDiscipline
from openlego.utils.xml_utils import xml_safe_create_element
from kadmos.utilities.xmls import xml_safe_create_element
class Performance(AbstractDiscipline):
......
......@@ -16,7 +16,7 @@ from lxml import etree
from examples.knowledgebases.ssbj import root_tag, x_h, x_M, x_ESF, x_D, x_Temp, x_SFC, x_WE, x_DT, x_WBE, x_T
from examples.knowledgebases.ssbj.common import PolynomialFunction, add_discipline_to_cmdows, run_tool
from openlego.api import AbstractDiscipline
from openlego.utils.xml_utils import xml_safe_create_element
from kadmos.utilities.xmls import xml_safe_create_element
class Propulsion(AbstractDiscipline):
......
......@@ -18,7 +18,7 @@ from examples.knowledgebases.ssbj import root_tag, x_tc, x_AR, x_Lambda, x_Sref,
x_L, x_Nz, x_WT, x_WF, x_sigma1, x_sigma2, x_sigma3, x_sigma4, x_sigma5, x_Theta
from examples.knowledgebases.ssbj.common import PolynomialFunction, add_discipline_to_cmdows, run_tool
from openlego.api import AbstractDiscipline
from openlego.utils.xml_utils import xml_safe_create_element
from kadmos.utilities.xmls import xml_safe_create_element
class Structures(AbstractDiscipline):
......
......@@ -2,6 +2,8 @@ import re
import ast
import logging
import numpy as np
from collections import OrderedDict
from lxml import etree
......@@ -16,6 +18,13 @@ logger = logging.getLogger(__name__)
# Settings for the parser
parser = etree.XMLParser(remove_blank_text=True)
# Patterns for XML attribute names and values
pttrn_attr_val = r'([-.0-9:A-Z_a-z]+?)'
pttrn_attr_name = r'([:A-Z_a-z][0-9:A-Z_a-z]*?)'
# Regular expressions to match attributes and indices within valid XPaths
re_atr = re.compile(r'\[@' + pttrn_attr_name + "=['\"]" + pttrn_attr_val + "['\"]\]")
re_ind = re.compile(r'\[([0-9]+?)\]')
def recursively_stringify(tree):
"""
......@@ -412,6 +421,133 @@ class ExtendedElement(etree.ElementBase):
return dictionary
def xml_safe_create_element(
tree, # type: etree._ElementTree
xpath, # type: str
value=None # type: Optional[Union[str, int, float, List[Union[str, int, float]], np.ndarray]]
):
# type: (object, object, object) -> object
# type: (...) -> etree._Element
"""Method taken from OpenLEGO package by Daniel de Vries:
Create an element at the given XML XPath with the given value.
This method ensures that all elements implied by the given X-Path exist.
Supplying a value is optional. If no value is supplied an empty XML node is created at the deepest level implied by
the XPath.
Parameters
----------
tree : :obj:`etree._ElementTree`
`etree._ElementTree` in which to create the element.
xpath : str
XPath to ensure.
value : str or int or float or list of str or list of int or list of float or :obj:`np.ndarray`
Optional value to write at the deepest node of the ensured XPath.
Returns
-------
:obj:`etree._Element`
Instance of `etree._Element` corresponding to the newly created element.
"""
# Split the xpath to get the intermediate nodes as a list
xpath_list = xpath.split('/')
n = len(xpath_list)
# Loop over the elements in the XPath from tip to root until the XPath is found to already exist
elem = None
i = 0
for i in range(0, n - 1):
xpath = '/'.join(xpath_list[0:(n - i)])
try:
elems = tree.xpath(xpath)
if len(elems):
elem = elems[0]
break
except etree.XPathError:
raise ValueError('Specified XPath is invalid')
# If no existing element was found the root elements of the tree and XPath don't match
if elem is None:
raise ValueError("Specified XPath is incompatible with the given XML tree: root tags don't match")
# Loop over the part of the XPath beyond this point and create all intermediate elements including attributes
for j in range(n - i, n):
tag = xpath_list[j]
# See if this node has an integer index specified
match_ind = re_ind.search(tag)
if match_ind:
tag = tag[:match_ind.start()] + tag[match_ind.end():]
index = int(match_ind.group(1)) - 1
else:
index = 0
# Find any attributes at this node
attrib = {}
match_attr = list(re_atr.finditer(tag))
if match_attr:
# Loop over all attributes on this node
for match in match_attr:
if match.start() < len(tag):
tag = tag[:match.start()]
attrib.update({match.group(1): match.group(2)})
# Check if there are siblings with the same name
siblings = elem.findall(tag)
n_siblings = len(siblings)
# Check if there's a sibling with the same name at this index without conflicting attributes
if index < n_siblings and not any(
[siblings[index].attrib[key] != attrib[key] for key in attrib.keys() if key in siblings[index].attrib]):
# If so, use it instead of adding a new one
siblings[index].attrib.update(attrib)
elem = siblings[index]
elif index <= n_siblings:
# In this case just append a new element
_elem = etree.Element(tag, attrib)
elem.append(_elem)
elem = _elem
else:
# In the last case, insert as many empty siblings until this node's index
sibling = None
for i in range(index - n_siblings):
_sibling = etree.Element(tag)
if i == 0:
if not n_siblings:
elem.append(_sibling)
else:
siblings[-1].addnext(_sibling)
else:
sibling.addnext(_sibling)
sibling = _sibling
# Finally at a new element at the right index with all attributes
elem = etree.Element(tag, attrib)
sibling.addnext(elem)
# Finally we can update the current XPath, since it has been assured to exist at this point
xpath = '/'.join([xpath, xpath_list[j]])
# If a value was supplied assign it to the deepest element in the XPath
if value is not None:
if isinstance(value, np.ndarray):
value = np.atleast_1d(value).flatten()
if isinstance(value, np.ndarray):
if value.size == 1:
elem.text = str(value[0])
else:
elem.text = ';'.join([str(v) for v in value[:]])
elem.attrib.update({'mapType': 'vector'})
else:
elem.text = str(value)
return elem
# Set element on the module level
parser.set_element_class_lookup(etree.ElementDefaultClassLookup(element=ExtendedElement))
Element = parser.makeelement
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment