"""
Author: HECE - University of Liege, Pierre Archambeau
Date: 2024
Copyright (c) 2024 University of Liege. All rights reserved.
This script and its content are protected by copyright law. Unauthorized
copying or distribution of this file, via any medium, is strictly prohibited.
"""
import wx
import numpy as np
from scipy.spatial import cKDTree
from OpenGL.GL import *
import logging
from typing import Union,Literal
from os.path import exists
from pathlib import Path
from .cst_2D_boundary_conditions import BCType_2D_OO, BCType_2D, ColorsNb, choose_bc_type, Direction, BCType_2D_GPU
from ..PyTranslate import _
from ..wolf_array import WolfArray
from .wolf2dprev import prev_boundary_conditions, boundary_condition_2D, prev_parameters_simul
[docs]
class BcManager(wx.Frame):
"""Boundary conditions Manager for WOLF"""
def __init__(self,
parent = None,
linked_array:WolfArray = None,
dx = 1.,
dy = 1.,
ox = 0.,
oy = 0.,
version=2,
title = _("Boundary Condition manager"),
width = 500,
height = 500,
DestroyAtClosing=False,
Callback=None,
mapviewer=None,
wolfparent=None,
*args, **kwargs):
self.wolfparent = wolfparent
self._filename_cl = ''
self._filename_sux = ''
self.dx = dx
self.dy = dy
self.orig= [ox,oy]
self._linked_array = linked_array
self.nb_borders = 0
self.mapviewer = mapviewer
if linked_array is not None:
self.dx = linked_array.dx
self.dy = linked_array.dy
self.orig = [linked_array.origx+linked_array.translx,
linked_array.origy+linked_array.transly]
self._version = version
self.bc_type = choose_bc_type(version)
self.bordersX:dict['bc':dict[str:str, 'nb':int],'selected':np.ndarray,'indices':np.ndarray,'indicesstr':list,'coords':np.ndarray,'coordscg':np.ndarray]
self.bordersY:dict['bc':dict[str:str, 'nb':int],'selected':np.ndarray,'indices':np.ndarray,'indicesstr':list,'coords':np.ndarray,'coordscg':np.ndarray]
self.bordersX={}
self.bordersY={}
self.bordersX['bc']={}
self.bordersY['bc']={}
self.colors_X = None
self.colors_Y = None
# bordersX and bordersY will contain
#
# 'bc' : dict where keys are 'i-j' (1-based) and containing all BC value and type
# 'selected' : numpy array of boolean
# 'indices' : border's reference in indices - Numpy array - shape (2,nbx),dtype=np.integer
# 'indicesstr' : list with string 'ii-jj'
# 'coords' : border's extremities - Numpy array - shape (2,2,nbx/nby),dtype=float
# 'coordscg' : border's gravity center - Numpy array - shape (2,nbx/nby),dtype=float
self._filecontent = ''
self.wx_exists = wx.App.Get() is not None # test if wx App is running
self.shader_program = None
self.VAO = None
self.VBO = None
self.buf_vertices = np.asarray([])
if self.wx_exists:
super(BcManager, self).__init__(parent, title = title,size = (width,height))
self._DestroyAtClosing = DestroyAtClosing
self._Callback = Callback
self.init_2D()
self.Show(True)
self._plot_init()
if wolfparent is not None:
self.FindBorders()
self.parse(wolfparent.sim.bc2txt())
self.update_colors()
@property
[docs]
def linked_array(self):
return self._linked_array
@property
[docs]
def get_fname_cl(self):
return self._filename_cl
@property
[docs]
def get_fname_sux_suy(self):
if self._filename_sux !='':
return self._filename_sux, self._filename_sux.replace('sux','suy')
else:
return '',''
[docs]
def init_2D(self):
"""Init wx Frame"""
self.sizer = wx.BoxSizer(wx.VERTICAL)
#Premiers boutons
self.sizerbut1 = wx.BoxSizer(wx.HORIZONTAL)
self.butLoad = wx.Button(self,wx.ID_ANY,"Load from file...")
self.butLoad.Bind(wx.EVT_BUTTON,self.OnLoad)
self.butSave = wx.Button(self,wx.ID_ANY,"Write to file...")
self.butSave.Bind(wx.EVT_BUTTON,self.OnSave)
self.sizerbut1.Add(self.butLoad,1,wx.EXPAND)
self.sizerbut1.Add(self.butSave,1,wx.EXPAND)
self.sizerbut2 = wx.BoxSizer(wx.HORIZONTAL)
self.butSet = wx.Button(self,wx.ID_ANY,"Set BC")
self.butSet.Bind(wx.EVT_BUTTON,self.OnSetBC)
self.butSet.SetToolTip(_('Impose BC for the selected borders'))
self.butGet = wx.Button(self,wx.ID_ANY,"Get BC")
self.butGet.Bind(wx.EVT_BUTTON,self.OnGetBC)
self.butGet.SetToolTip(_('Retrieve BC for the selected borders'))
self.butReset = wx.Button(self,wx.ID_ANY,"Reset BC")
self.butReset.Bind(wx.EVT_BUTTON,self.OnResetBC)
self.butReset.SetToolTip(_('Reset all BC values'))
self.sizerbut2.Add(self.butSet,1,wx.EXPAND)
self.sizerbut2.Add(self.butGet,1,wx.EXPAND)
self.sizerbut2.Add(self.butReset,1,wx.EXPAND)
#type de CL en "collapsable"
self.sizerAllBC = wx.BoxSizer(wx.VERTICAL)
self.sizerAllBCt = wx.BoxSizer(wx.VERTICAL)
self._sizerBC = {}
self._checkBC = {}
self._labelBC = {}
self._valueBC = {}
self._findBC = {}
self.collpane = wx.CollapsiblePane(self, wx.ID_ANY, "Type of BC:")
win = self.collpane.GetPane()
self.sizerAllBC.Add(self.collpane,1,wx.EXPAND|wx.GROW| wx.ALL)
for curbc in self.bc_type:
valbc, name_bc = curbc.value
self._sizerBC[name_bc] = wx.BoxSizer(wx.HORIZONTAL)
self._checkBC[name_bc] = wx.CheckBox(win)
self._labelBC[name_bc] = wx.StaticText(win,label=name_bc,size=(200,20))
self._valueBC[name_bc] = wx.TextCtrl(win,size=(100,20),style=wx.TE_CENTRE)
self._findBC[name_bc] = wx.Button(win,name=name_bc,label="Find all",size=(60,20))
self._findBC[name_bc].Bind(wx.EVT_BUTTON,self.OnFind)
self._sizerBC[name_bc].Add(self._checkBC[name_bc],0,wx.GROW)
self._sizerBC[name_bc].Add(self._labelBC[name_bc],0,wx.FIXED_MINSIZE|wx.GROW)
self._sizerBC[name_bc].Add(self._valueBC[name_bc],1,wx.FIXED_MINSIZE|wx.GROW|wx.EXPAND)
self._sizerBC[name_bc].Add(self._findBC[name_bc],0,wx.GROW)
self.sizerAllBCt.Add(self._sizerBC[name_bc],1,wx.EXPAND)
win.SetSizer(self.sizerAllBCt)
#Zone de selection
self.sizerselectAll = wx.BoxSizer(wx.VERTICAL)
self.sizerselect = wx.BoxSizer(wx.VERTICAL)
self.collpaneSelect = wx.CollapsiblePane(self, wx.ID_ANY, "Selected Borders:")
win = self.collpaneSelect.GetPane()
self.sizerselectAll.Add(self.collpaneSelect,1,wx.EXPAND|wx.GROW| wx.ALL)
self.sizerselButtons = wx.BoxSizer(wx.HORIZONTAL)
self.butClear = wx.Button(win,wx.ID_CLEAR,"Unselect all")
self.butClear.Bind(wx.EVT_BUTTON,self.OnClearselection)
self.butFind = wx.Button(win,wx.ID_CLEAR,"Find borders")
self.butFind.Bind(wx.EVT_BUTTON,self.OnFindBorders)
self.sizerselButtons.Add(self.butClear,1,wx.EXPAND|wx.GROW)
self.sizerselButtons.Add(self.butFind,1,wx.EXPAND|wx.GROW)
self.sizercmdx = wx.BoxSizer(wx.HORIZONTAL)
self.sizercmdy = wx.BoxSizer(wx.HORIZONTAL)
self.labelcmdx = wx.StaticText(win,label='X:')
self.cmdx = wx.TextCtrl(win,size=(490,20),style=wx.TE_PROCESS_TAB)
self.sizercmdx.Add(self.labelcmdx,0,wx.GROW)
self.sizercmdx.Add(self.cmdx,1,wx.FIXED_MINSIZE|wx.GROW)
self.labelcmdy = wx.StaticText(win,label='Y:')
self.cmdy = wx.TextCtrl(win,size=(490,20),style=wx.TE_PROCESS_TAB)
self.sizercmdy.Add(self.labelcmdy,0,wx.GROW)
self.sizercmdy.Add(self.cmdy,1,wx.FIXED_MINSIZE|wx.GROW)
self.sizerselcommand = wx.BoxSizer(wx.VERTICAL)
self.labelcmd = wx.StaticText(win,label='Selection')
self.labelexample = wx.StaticText(win,label='example : 5,6,10-20 tab 10,20,40-60')
self.sizerselcommand.Add(self.labelcmd,0,wx.GROW)
self.sizerselcommand.Add(self.labelexample,0,wx.GROW)
self.sizerselcommand.Add(self.sizercmdx,1,wx.EXPAND)
self.sizerselcommand.Add(self.sizercmdy,1,wx.EXPAND)
self.sizerTextBoxes = wx.BoxSizer(wx.HORIZONTAL)
self.sizerTextBoxX = wx.BoxSizer(wx.VERTICAL)
self.sizerTextBoxY = wx.BoxSizer(wx.VERTICAL)
self.labelBCx = wx.StaticText(win,label='Borders along X axis |')
self.BCx = wx.TextCtrl(win,size=(250,250),style=wx.TE_MULTILINE|wx.TE_PROCESS_TAB)
self.sizerTextBoxX.Add(self.labelBCx,0,wx.GROW)
self.sizerTextBoxX.Add(self.BCx,1,wx.GROW|wx.EXPAND)
self.labelBCy = wx.StaticText(win,label='Borders along Y axis _')
self.BCy = wx.TextCtrl(win,size=(250,250),style=wx.TE_MULTILINE|wx.TE_PROCESS_TAB)
self.sizerTextBoxY.Add(self.labelBCy,0,wx.GROW)
self.sizerTextBoxY.Add(self.BCy,1,wx.GROW|wx.EXPAND)
self.sizerTextBoxes.Add(self.sizerTextBoxX,1,wx.EXPAND)
self.sizerTextBoxes.Add(self.sizerTextBoxY,1,wx.EXPAND)
self.sizerselect.Add(self.sizerselcommand,0,wx.EXPAND)
self.sizerselect.Add(self.sizerselButtons,0,wx.EXPAND)
self.sizerselect.Add(self.sizerTextBoxes,0,wx.EXPAND)
win.SetSizer(self.sizerselect)
self.sizerfile = wx.BoxSizer(wx.HORIZONTAL)
self.sizerButtonSAction = wx.BoxSizer(wx.VERTICAL)
self.File = wx.TextCtrl(self,size=(500,250),style=wx.TE_MULTILINE|wx.TE_PROCESS_TAB)
self.FileCmd=wx.Button(self,label='Apply to memory')
self.FileCmd.Bind(wx.EVT_BUTTON,self.OnFileCmd)
self.FileCmd.SetToolTip(_('Apply modifications from the textbox to memory'))
self.to_clipboard=wx.Button(self,label='Copy script to clipboard')
self.to_clipboard.Bind(wx.EVT_BUTTON,self.OnCopyToClipboard)
self.to_clipboard.SetToolTip(_('Copy script lines to clipboard'))
self.quitbutton=wx.Button(self,label=_('Quit'))
self.quitbutton.Bind(wx.EVT_BUTTON,self.OnDestroy)
self.quitbutton.SetToolTip(_('Close the window and quit'))
self.sizerfile.Add(self.File,3,wx.EXPAND)
self.sizerfile.Add(self.sizerButtonSAction,1,wx.EXPAND)
self.sizerButtonSAction.Add(self.FileCmd,1,wx.EXPAND)
self.sizerButtonSAction.Add(self.to_clipboard,1,wx.EXPAND)
self.sizerButtonSAction.Add(self.quitbutton,1,wx.EXPAND)
self.sizer.Add(self.sizerbut1,0,wx.EXPAND)
self.sizer.Add(self.sizerbut2,0,wx.EXPAND)
self.sizer.Add(self.sizerAllBC,0,wx.EXPAND)
self.sizer.Add(self.sizerselectAll,0,wx.EXPAND)
self.sizer.Add(self.sizerfile,1,wx.EXPAND)
self.Bind(wx.EVT_CLOSE,self.OnClose)
self.SetSizer(self.sizer)
self.sizer.Fit(self)
self.SetAutoLayout(1)
[docs]
def OnClose(self, event:wx.MouseEvent):
""" Close the window """
if self._DestroyAtClosing:
self._Callback(self)
self.Destroy()
else:
self.Hide()
pass
[docs]
def OnDestroy(self, event:wx.MouseEvent):
""" Close the window """
self._Callback(self)
self.Destroy()
[docs]
def LoadFile(self,filename:str):
"""
Read file
:param filename: name of file to read
"""
if filename.endswith('cl'):
#lecture du contenu
with open(filename, 'r') as myfile:
txt = myfile.read()
myfile.close()
self._filename_cl = filename
self._filecontent = txt.replace(',','\t')
elif filename.endswith('.par'):
prev_param = prev_parameters_simul()
prev_param.read_file(filename)
lst_x = prev_param.weak_bc_x.mybc
lst_y = prev_param.weak_bc_y.mybc
self._filecontent = str(len(lst_x)+len(lst_y)) +'\n'
for curbc in lst_x:
self._filecontent += '{}\t{}\t{}\t{}\t{}'.format(curbc.i,
curbc.j,
1,
curbc.ntype,
curbc.val)
for curbc in lst_y:
self._filecontent += '{}\t{}\t{}\t{}\t{}'.format(curbc.i,
curbc.j,
2,
curbc.ntype,
curbc.val)
self._filename_cl = filename + '.cl'
self.prev_param = None
[docs]
def OnLoad(self,event:wx.MouseEvent):
""" Click on Load button """
#ouverture d'une boîte de dialogue
file=wx.FileDialog(self,"Choose file",
wildcard="Boundary conditions (*.cl)|*.cl|Parameter file (*.par)|*.par|all (*.*)|*.*")
if file.ShowModal() == wx.ID_CANCEL:
file.Destroy()
return
else:
#récuparétaion du nom de fichier avec chemin d'accès
filename =file.GetPath()
file.Destroy()
self.LoadFile(filename)
self.File.Value = self._filecontent
[docs]
def SaveFile(self,filename:str=None):
"""
Save to file
:param filename: name of file to write
"""
if filename is None and self._filename_cl =='':
logging.info(_('Nothing to do - choose a filename and retry !'))
return
if filename is None:
filename = self._filename_cl
if filename is not None:
self._filename_cl = filename
#écriture du contenu
with open(filename, 'w') as myfile:
myfile.write(self._filecontent)
myfile.close()
[docs]
def OnSave(self,event:wx.MouseEvent):
""" Click on Save button """
#ouverture d'une boîte de dialogue
file=wx.FileDialog(self,
"Choose file",
wildcard="Boundary conditions (*.cl)|*.cl|all (*.*)|*.*")
if file.ShowModal() == wx.ID_CANCEL:
file.Destroy()
return
else:
#récuparétaion du nom de fichier avec chemin d'accès
filename =file.GetPath()
file.Destroy()
self.SaveFile(filename)
[docs]
def FindBC(self, bc_type:str) -> tuple[str,str]:
"""
Find indices of borders with associated 'whichbc' value
:param whichbc: type of BC to find
:return 2 strings with indices along X and Y -- 'i\tj\n'
"""
textx=''
texty=''
curdict:dict=self.bordersX['bc']
key:str
allbc:dict
for key, allbc in curdict.items():
try:
i,j=key.split('-')
if bc_type in allbc.keys():
if(str(allbc[bc_type]) != '99999.0'):
textx+=i+'\t'+j+'\n'
except:
pass
curdict:dict=self.bordersY['bc']
for key, allbc in curdict.items():
try:
i,j=key.split('-')
if bc_type in allbc.keys():
if(str(allbc[bc_type]) != '99999.0'):
texty+=i+'\t'+j+'\n'
except:
pass
return textx, texty
[docs]
def OnFind(self,event:wx.MouseEvent):
"""
Find all borders associated with
and put strings in widgets
"""
#get the type of BC based on name
tbc=event.EventObject.Name
textx, texty = self.FindBC(tbc)
self.BCx.Clear()
self.BCy.Clear()
self.BCx.Value=textx
self.BCy.Value=texty
self.GetBC()
[docs]
def OnSetBC(self,event:wx.MouseEvent):
"""
Click on Apply button
Parse BC from textboxes and apply to memory
"""
for sel, curbord in zip([self.BCx.Value.splitlines(),self.BCy.Value.splitlines()],
[self.bordersX, self.bordersY]):
for cursel in sel:
i,j=cursel.split('\t')
txt=str(i)+'-'+str(j)
try:
mybc= curbord['bc'][txt]
except:
mybc=curbord['bc'][txt]={}
for k,tbc in enumerate(self._checkBC.keys()):
if self._checkBC[tbc].Value:
if self._valueBC[tbc].Value!='':
mybc[tbc]=float(self._valueBC[tbc].Value)
self.resetBC()
self._Populate_FileContent()
self.update_colors()
[docs]
def resetBC(self):
"""Reset all wx widgets related to BC"""
if self.wx_exists:
for curbc in self.bc_type:
val_bc, name_bc = curbc.value
self._checkBC[name_bc].Value=False
self._valueBC[name_bc].Value=''
self.update_colors()
[docs]
def OnResetBC(self,event:wx.MouseEvent):
""" Click on Reset button """
self.resetBC()
[docs]
def GetBC(self):
"""
Get BC for selected borders
"""
# create dictionary for all BC values
values={}
for curbc in self.bc_type:
valbc, tbc = curbc.value
values[tbc]={}
values[tbc]['val']={}
values[tbc]['same']=True
values[tbc]['nb']=0
# iterate along X == 0 and Y == 1
for xy in range(2):
if xy==0:
sel=self.BCx.Value.splitlines()
curbord=self.bordersX
else:
sel=self.BCy.Value.splitlines()
curbord=self.bordersY
# iterate on borders
for cursel in sel:
i,j=cursel.split('\t')
txt=str(i)+'-'+str(j)
try:
# count number of BC of each type and determine if all BC are the same
mybc= curbord['bc'][txt]
for ibc,tbc in enumerate(mybc):
curval=float(mybc[tbc])
if values[tbc]['nb']>0:
if not curval in values[tbc]['val'].values():
values[tbc]['nb']+=1
values[tbc]['val'][values[tbc]['nb']]=curval
values[tbc]['same']=False
else:
values[tbc]['nb']+=1
values[tbc]['val'][values[tbc]['nb']]=curval
except:
pass
# update widgets
for curbc in self.bc_type:
valbc, tbc = curbc.value
if values[tbc]['nb']>0:
self._checkBC[tbc].Value=True
txt=''
if values[tbc]['same']:
for curval in values[tbc]['val'].values():
txt += str(curval)
else:
for curval in values[tbc]['val'].values():
txt += str(curval) +' or '
txt+='...'
self._valueBC[tbc].Value=txt
else:
self._checkBC[tbc].Value=False
[docs]
def OnGetBC(self,event:wx.MouseEvent):
""" Click on Get button """
self.GetBC()
[docs]
def Clearselection(self):
""" Clear selection """
self.bordersX['selected'][:]=False
self.bordersY['selected'][:]=False
self.update_colors()
[docs]
def OnClearselection(self,event:wx.MouseEvent):
""" Clear selection """
self.Clearselection()
self.update_selection()
[docs]
def OnFindBorders(self,event:wx.MouseEvent):
"""
Click on Find borders Button
Parsing of textboxes and update selection
"""
if self.cmdx.Value!='':
tx = self.cmdx.Value.split('\t')
if len(tx)==2:
indi={}
indj={}
partxi = tx[0].split(',')
for i,curpart in enumerate(partxi):
indi[i]={}
bounds=curpart.split('-')
indi[i]['chain']=curpart
indi[i]['istart']=int(bounds[0])-1
try:
indi[i]['iend']=int(bounds[1])-1
except:
indi[i]['iend']=int(bounds[0])-1
partxj = tx[1].split(',')
for i,curpart in enumerate(partxj):
indj[i]={}
bounds=curpart.split('-')
indj[i]['chain']=curpart
indj[i]['jstart']=int(bounds[0])-1
try:
indj[i]['jend']=int(bounds[1])-1
except:
indj[i]['jend']=int(bounds[0])-1
for whichi in indi.keys():
for i in range(indi[whichi]['istart'],indi[whichi]['iend']+1):
for whichj in indj.keys():
for j in range(indj[whichj]['jstart'],indj[whichj]['jend']+1):
text=str(i)+'-'+str(j)
try:
index=self.bordersX['indicesstr'].index(text)
self.bordersX['selected'][index] = ~ self.bordersX['selected'][index]
except:
pass
else:
logging.info(_('Bad command for X borders -- Nothing to do !'))
if self.cmdy.Value!='':
ty = self.cmdy.Value.split('\t')
if len(ty)==2:
indi={}
indj={}
partyi = ty[0].split(',')
for i,curpart in enumerate(partyi):
indi[i]={}
bounds=curpart.split('-')
indi[i]['chain']=curpart
indi[i]['istart']=int(bounds[0])-1
try:
indi[i]['iend']=int(bounds[1])-1
except:
indi[i]['iend']=int(bounds[0])-1
partyj = ty[1].split(',')
for i,curpart in enumerate(partyj):
indj[i]={}
bounds=curpart.split('-')
indj[i]['chain']=curpart
indj[i]['jstart']=int(bounds[0])-1
try:
indj[i]['jend']=int(bounds[1])-1
except:
indj[i]['jend']=int(bounds[0])-1
for whichi in indi.keys():
for i in range(indi[whichi]['istart'],indi[whichi]['iend']+1):
for whichj in indj.keys():
for j in range(indj[whichj]['jstart'],indj[whichj]['jend']+1):
text=str(i)+'-'+str(j)
try:
index=self.bordersY['indicesstr'].index(text)
self.bordersY['selected'][index] = ~ self.bordersY['selected'][index]
except:
pass
else:
wx.MessageBox('Bad command for Y borders -- Nothing to do !')
self.update_colors()
self._Populate_selxy()
[docs]
def update_selection(self):
if self.wx_exists:
self._Populate_selxy()
[docs]
def _Populate_selxy(self):
"""Set selected along X and Y"""
textx=''
for k,selected in enumerate(self.bordersX['selected']):
if selected:
textx+= str(self.bordersX['indices'][0][k]+1) + '\t'+ str(self.bordersX['indices'][1][k]+1)+'\n'
texty=''
for k,selected in enumerate(self.bordersY['selected']):
if selected:
texty+= str(self.bordersY['indices'][0][k]+1) + '\t'+ str(self.bordersY['indices'][1][k]+1)+'\n'
if self.wx_exists:
self.BCx.Clear()
self.BCx.AppendText(textx)
self.BCy.Clear()
self.BCy.AppendText(texty)
return textx, texty
[docs]
def _Populate_FileContent(self):
"""
Update file content
"""
text=''
nb=0
for orient in range(1,3):
if orient==1:
curlist=self.bordersX['bc']
else:
curlist=self.bordersY['bc']
curlist:dict
ij:str
allbc:dict
for ij, allbc in curlist.items():
for tbc, val in allbc.items():
i,j=ij.split('-')
numbc=self._find_Int_TypeBC(tbc)
if(str(val)!='99999.0'):
text+= "{}\t{}\t{}\t{}\t{}\n".format(i,j,orient,numbc,val)
nb+=1
self._filecontent = str(nb)+'\n'
self._filecontent += text+'\n'
self._filecontent += 'version {}'.format(self._version)
self._filecontent += '\n\n'
self._filecontent += self._script_bc()
if self.wx_exists:
self.File.Clear()
self.File.Value=self._filecontent
[docs]
def _script_bc(self):
""" Return script to apply BC """
text = ""
for orient in range(1,3):
if orient==1:
curlist=self.bordersX['bc']
direction='LEFT'
else:
curlist=self.bordersY['bc']
direction='BOTTOM'
curlist:dict
ij:str
allbc:dict
for ij, allbc in curlist.items():
for tbc, val in allbc.items():
i,j=ij.split('-')
namebc=self._find_EnumName_TypeBC(tbc)
if(str(val)!='99999.0'):
text+= "simul.add_boundary_condition(i={}, j={},bc_type=BoundaryConditionsTypes.{}, bc_value={}, border=Direction.{})\n".format(i,j,namebc,val,direction)
return text
[docs]
def send_to_wolfparent(self):
"""
Send BC to parent
"""
from ..PyGui import Wolf2DModel, Wolf2DGPUModel
if self.wolfparent is not None:
if isinstance(self.wolfparent, Wolf2DModel):
self.wolfparent.reset_boundary_conditions()
for orient in range(1,3):
if orient==1:
curlist=self.bordersX['bc']
direction=Direction.LEFT
else:
curlist=self.bordersY['bc']
direction=Direction.BOTTOM
curlist:dict
ij:str
allbc:dict
for ij, allbc in curlist.items():
for tbc, val in allbc.items():
i,j=ij.split('-')
namebc=self._find_Enum_TypeBC(tbc)
if(str(val)!='99999.0'):
self.wolfparent.add_boundary_condition(int(i), int(j), namebc, float(val), direction)
self.wolfparent._show_glob_properties()
elif isinstance(self.wolfparent, Wolf2DGPUModel):
self.wolfparent.reset_boundary_conditions()
for orient in range(1,3):
if orient==1:
curlist=self.bordersX['bc']
direction=Direction.LEFT
else:
curlist=self.bordersY['bc']
direction=Direction.BOTTOM
curlist:dict
ij:str
allbc:dict
for ij, allbc in curlist.items():
for tbc, val in allbc.items():
i,j=ij.split('-')
namebc=self._find_Enum_TypeBC(tbc)
if(str(val)!='99999.0'):
self.wolfparent.add_boundary_condition(int(i), int(j), namebc, float(val), direction)
[docs]
def parse(self, text:str):
"""
Parse text and fill bordersX and bordersY
"""
self._filecontent = text
text=text.splitlines()
if len(text) == 0:
return
nb=int(float(text[0]))
try:
for i in range(1,nb+1):
i,j,orient,type,value=text[i].split('\t')
except:
logging.info(_('Bad text values -- Check and Retry !!'))
return
self.bordersX['bc']={}
self.bordersY['bc']={}
for i in range(1,nb+1):
i,j,orient,type,value=text[i].split('\t')
i=int(float(i))
j=int(float(j))
type=int(float(type))
orient=int(float(orient))
value=float(value)
if orient==1:
texttxt=str(i)+'-'+str(j)
try:
index=self.bordersX['indicesstr'].index(texttxt)
try:
curbc =self.bordersX['bc'][str(i)+'-'+str(j)]
except:
curbc=self.bordersX['bc'][str(i)+'-'+str(j)]={}
try:
curbc[self._find_Str_TypeBC(type)]=value
except:
try:
curbc[type]=value
except:
pass
except:
logging.info('Bad border indices on X ('+str(i)+'-'+str(j)+(')'))
elif orient==2:
texttxt=str(i)+'-'+str(j)
try:
index=self.bordersY['indicesstr'].index(texttxt)
try:
curbc =self.bordersY['bc'][str(i)+'-'+str(j)]
except:
curbc=self.bordersY['bc'][str(i)+'-'+str(j)]={}
try:
curbc[self._find_Str_TypeBC(type)]=value
except:
try:
curbc[type]=value
except:
pass
except:
logging.info('Bad border indices on Y ('+str(i)+'-'+str(j)+(')'))
if self.wx_exists:
self._Populate_FileContent()
[docs]
def OnFileCmd(self,event:wx.MouseEvent):
""" Apply <<< button"""
self.parse(self.File.Value)
self.send_to_wolfparent()
[docs]
def OnCopyToClipboard(self,event:wx.MouseEvent):
""" Copy to clipboard"""
if self.wx_exists:
if wx.TheClipboard.Open():
wx.TheClipboard.Clear()
wx.TheClipboard.SetData(wx.TextDataObject(self._script_bc()))
wx.TheClipboard.Close()
else:
logging.warning(_('Cannot open the clipboard'))
[docs]
def FindBorders(self,array : np.ma.array = None):
"""Find all borders where we can impose BC"""
if self._linked_array is not None and array is None:
array = self._linked_array.array
elif self._linked_array is None and array is None:
return
elif self._linked_array is not None and array is not None:
pass
assert isinstance(array, np.ma.masked_array)
shape = array.shape
xor = np.logical_xor(array.mask[:-1,:],array.mask[1:,:])
yor = np.logical_xor(array.mask[:,:-1],array.mask[:,1:])
nbx_where = np.where(xor)
nby_where = np.where(yor)
nbx = len(nbx_where[0])
nby = len(nby_where[0])
self.bordersX['nb']=nbx
self.bordersY['nb']=nby
if nbx ==0 and nby ==0:
logging.warning(_('No border detected -- check your data'))
return -1
indicesX = np.zeros((2,nbx),dtype=np.integer,order='F')
indicesY = np.zeros((2,nby),dtype=np.integer,order='F')
indicesX[0,:] = np.asarray(nbx_where[0])+1
indicesX[1,:] = np.asarray(nbx_where[1])
indicesY[0,:] = np.asarray(nby_where[0])
indicesY[1,:] = np.asarray(nby_where[1])+1
indicesXstr = [ str(i+1)+'-'+str(j+1) for i, j in indicesX.T]
indicesYstr = [ str(i+1)+'-'+str(j+1) for i, j in indicesY.T]
self.bordersX['indices']=indicesX
self.bordersX['indicesstr']=indicesXstr
self.bordersY['indices']=indicesY
self.bordersY['indicesstr']=indicesYstr
self._ComputeCoordinates()
self._do_kdtree()
if self.wx_exists:
self.update_colors()
[docs]
def ReadFileBorders(self,*args):
"""
Read sux and suy files
Provide path to .sux file
.suy file is supposed to be in the same directory
"""
if len(args)>0:
#s'il y a un argument on le prend tel quel
self._filename_sux = str(args[0])
else:
if self.wx_exists:
#ouverture d'une boîte de dialogue
file=wx.FileDialog(self,"Choose file", wildcard="sux (*.sux)|*.sux|all (*.*)|*.*")
if file.ShowModal() == wx.ID_CANCEL:
file.Destroy()
return
else:
#récuparétaion du nom de fichier avec chemin d'accès
self._filename_sux =file.GetPath()
file.Destroy()
if self._filename_sux!='':
if not exists(self._filename_sux):
return
#lecture du contenu SUX
with open(self._filename_sux, 'r') as myfile:
#split des lignes --> récupération des infos sans '\n' en fin de ligne
# différent de .readlines() qui lui ne supprime pas les '\n'
myparamsline = myfile.read().splitlines()
myfile.close()
indicesX = np.zeros((2,myparamsline.count()),dtype=np.integer,order='F')
k=0
for myborder in myparamsline:
indicesX[:,k] = myborder.split()
k+=1
self.bordersX['nb']=indicesX.size()/2
self.bordersX['indices']=indicesX
#lecture du contenu SUX
suy = self._filename_sux.replace('sux','suy')
with open(suy, 'r') as myfile:
#split des lignes --> récupération des infos sans '\n' en fin de ligne
# différent de .readlines() qui lui ne supprime pas les '\n'
myparamsline = myfile.read().splitlines()
myfile.close()
indicesY = np.zeros((2,myparamsline.count()),dtype=np.integer,order='F')
k=0
for myborder in myparamsline:
indicesY[:,k] = myborder.split()
k+=1
self.bordersY['nb']=indicesY.size()/2
self.bordersY['indices']=indicesY
[docs]
def _ComputeCoordinates(self):
"""Calculate and store positions of possible BC"""
nbx=self.bordersX['nb']
coordscgX = np.zeros((2,nbx),dtype=float,order='F')
coordsX = np.zeros((2,2,nbx),dtype=float,order='F')
selectedX = np.zeros(nbx,dtype=np.bool_,order='F')
for k in range(nbx):
x1=self.orig[0]+self.bordersX['indices'][0,k]*self.dx
y1=self.orig[1]+self.bordersX['indices'][1,k]*self.dy
y2=y1+self.dy
coordsX[0,0,k]=x1
coordsX[1,0,k]=y1
coordsX[0,1,k]=x1
coordsX[1,1,k]=y2
coordscgX[0,k]=x1
coordscgX[1,k]=(y1+y2)/2.
self.bordersX['coords']=coordsX
self.bordersX['coordscg']=coordscgX
self.bordersX['selected']=selectedX
nby=self.bordersY['nb']
coordscgY = np.zeros((2,nby),dtype=float,order='F')
coordsY = np.zeros((2,2,nby),dtype=float,order='F')
selectedY = np.zeros(nby,dtype=np.bool_,order='F')
for k in range(nby):
x1=self.orig[0]+self.bordersY['indices'][0,k]*self.dx
x2=x1+self.dx
y1=self.orig[1]+self.bordersY['indices'][1,k]*self.dy
coordsY[0,0,k]=x1
coordsY[1,0,k]=y1
coordsY[0,1,k]=x2
coordsY[1,1,k]=y1
coordscgY[0,k]=(x1+x2)/2.
coordscgY[1,k]=y1
self.bordersY['coords']=coordsY
self.bordersY['coordscg']=coordscgY
self.bordersY['selected']=selectedY
[docs]
def _nb_bc(self, bc:dict) -> int:
"""
Count number of BC for border 'bc'
:param bc: dict of BC for a border
"""
nb=0
for valbc in bc.values():
if valbc != '99999.0':
nb+=1
return nb
[docs]
def _get_index(self, key:str, dictXY:dict) -> int:
"""
Get index of key in dictXY
:param key: key to find
:param dictXY: dictionary of borders -- self.borderX or self.borderY
"""
i,j=key.split('-')
index=dictXY['indicesstr'].index(key)
return index
[docs]
def default_colors(self):
""" allocate colors and set default to black """
self.colors_X = np.zeros((self.bordersX['nb'],3),dtype=np.float32)
self.colors_Y = np.zeros((self.bordersY['nb'],3),dtype=np.float32)
[docs]
def update_colors(self):
""" Update colors for OpenGL """
self._color_bc()
self._update_buffer()
if self.mapviewer is not None:
self.mapviewer.Refresh()
[docs]
def _color_bc(self):
""" Color borders according to number of BC """
nbmax_colors = len(ColorsNb)
self.default_colors()
# Find number of BC for each border
nb = [self._nb_bc(curbc) for curbc in self.bordersX['bc'].values()]
# find index of each border with BC
indices = np.asarray([self._get_index(key, self.bordersX) for key in self.bordersX['bc'].keys()])
if len(indices) >0:
# get colors for each border with BC
colors_X_BC = np.asarray([ColorsNb[curnb] if curnb>0 and curnb <= nbmax_colors else (0.,0.,0.) for curnb in nb], dtype=np.float32)
# replace default color with BC colors
self.colors_X[indices] = colors_X_BC
# same for Y
nb = [self._nb_bc(curbc) for curbc in self.bordersY['bc'].values()]
indices = np.asarray([self._get_index(key, self.bordersY) for key in self.bordersY['bc'].keys()])
if len(indices) >0:
colors_Y_BC = np.asarray([ColorsNb[curnb] if curnb>0 and curnb <= nbmax_colors else (0.,0.,0.) for curnb in nb], dtype=np.float32)
self.colors_Y[indices] = colors_Y_BC
# set selected borders to red
sel_x = np.where(self.bordersX['selected'])[0]
self.colors_X[sel_x] = np.asarray([1.,0.,0.], dtype=np.float32)
sel_y = np.where(self.bordersY['selected'])[0]
self.colors_Y[sel_y] = np.asarray([1.,0.,0.], dtype=np.float32)
#tile
self.colors_X = np.tile(self.colors_X,2)
self.colors_Y = np.tile(self.colors_Y,2)
[docs]
def _get_colors(self) -> np.ndarray:
""" Concatenate colors for X and Y """
# we must tile colors for each point of the border
return np.concatenate((self.colors_X,self.colors_Y), axis=0).flatten()
[docs]
def _get_coords(self) -> np.ndarray:
""" Concatenate coordinates for X and Y """
pass
return np.concatenate((self.bordersX['coords'].transpose(), self.bordersY['coords'].transpose()), axis=0)
[docs]
def _plot_init(self):
""" Initialize OpenGL - Program shader"""
pass
vertex_shader = glCreateShader(GL_VERTEX_SHADER)
# glShaderSource(vertex_shader, vertex_shader_source)
with open(Path(__file__).parent.parent / 'shaders/simple_vertex_shader.glsl', 'r') as myfile:
src_shader = myfile.read()
glShaderSource(vertex_shader, src_shader)
glCompileShader(vertex_shader)
if glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, None) == GL_FALSE:
info_log = glGetShaderInfoLog(vertex_shader)
print(info_log)
glDeleteProgram(vertex_shader)
raise Exception("Can't compile shader on GPU")
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
# glShaderSource(fragment_shader, fragment_shader_source)
with open(Path(__file__).parent.parent / 'shaders/simple_fragment_shader.glsl', 'r') as myfile:
src_shader = myfile.read()
glShaderSource(fragment_shader, src_shader)
glCompileShader(fragment_shader)
if glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, None) == GL_FALSE:
info_log = glGetShaderInfoLog(fragment_shader)
print(info_log)
glDeleteProgram(fragment_shader)
raise Exception("Can't compile shader on GPU")
self.shader_program = glCreateProgram()
glAttachShader(self.shader_program, vertex_shader)
glAttachShader(self.shader_program, fragment_shader)
glLinkProgram(self.shader_program)
# Check if the program is compiled
if glGetProgramiv(self.shader_program, GL_LINK_STATUS) == GL_FALSE:
info_log = glGetProgramInfoLog(self.shader_program)
print(info_log)
raise Exception("Can't link shader program")
glDeleteShader(vertex_shader)
glDeleteShader(fragment_shader)
[docs]
def _update_buffer(self):
""" Update OpenGL buffer """
pass
self.buf_vertices = self._get_coords()
self.buf_vertices = self.buf_vertices.flatten().astype(np.float32)
if self.colors_X is None or self.colors_Y is None:
self._color_bc()
self.buf_colors = self._get_colors()
assert self.buf_vertices.dtype == np.float32, 'vertices must be float32'
assert self.buf_colors.dtype == np.float32, 'colors must be float32'
# Créer un VAO (Vertex Array Object) et un VBO (Vertex Buffer Object)
if self.VAO is None:
self.VAO = glGenVertexArrays(1)
if self.VBO is None:
self.VBO = glGenBuffers(1)
# Lier le VAO
glBindVertexArray(self.VAO)
# Lier le VBO et copier les données des vertices et des couleurs
glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
glBufferData(GL_ARRAY_BUFFER, self.buf_vertices.nbytes + self.buf_colors.nbytes, None, GL_DYNAMIC_DRAW)
# Unbind VAO
glBindVertexArray(GL_NONE)
glBindBuffer(GL_ARRAY_BUFFER, GL_NONE)
# Lier le VAO
glBindVertexArray(self.VAO)
# Lier le VBO et copier les données des vertices et des couleurs
glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
# glBufferData(GL_ARRAY_BUFFER, self.buf_vertices.nbytes + self.buf_colors.nbytes, None, GL_DYNAMIC_DRAW)
# glBufferSubData(GL_ARRAY_BUFFER, 0, self.buf_vertices.nbytes, self.buf_vertices)
# glBufferSubData(GL_ARRAY_BUFFER, self.buf_vertices.nbytes, self.buf_colors.nbytes, self.buf_colors)
glBufferData(GL_ARRAY_BUFFER, self.buf_vertices.nbytes + self.buf_colors.nbytes, np.concatenate((self.buf_vertices, self.buf_colors)), GL_DYNAMIC_DRAW)
# Spécifier les attributs de position des vertices
# glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), ctypes.c_void_p(0))
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
# Spécifier les attributs de couleur
# glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), ctypes.c_void_p(self.buf_vertices.nbytes))
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(self.buf_vertices.nbytes))
glEnableVertexAttribArray(1)
# Unbind VAO
glBindVertexArray(0)
[docs]
def plot(self):
""" Plot borders -- OpenGL """
if len(self.buf_vertices)==0:
return
# with shader
# -----------
glUseProgram(self.shader_program)
glGetIntegerv(GL_CURRENT_PROGRAM, self.shader_program)
modelview, projection, viewport = self.mapviewer.get_MVP_Viewport_matrix()
# Bind VAO
glBindVertexArray(self.VAO)
# glBindBuffer(GL_ARRAY_BUFFER, self.VBO)
modelview_loc = glGetUniformLocation(self.shader_program, "modelview")
projection_loc = glGetUniformLocation(self.shader_program, "projection")
assert modelview_loc != -1, "modelview_loc == -1"
assert projection_loc != -1, "projection_loc == -1"
glUniformMatrix4fv(modelview_loc, 1, GL_FALSE, modelview)
glUniformMatrix4fv(projection_loc, 1, GL_FALSE, projection)
cmo_aVertex = glGetAttribLocation(self.shader_program, "aVertex")
glEnableVertexAttribArray(cmo_aVertex)
# Spécifier les attributs de position des vertices
# glVertexAttribPointer(cmo_aVertex, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), ctypes.c_void_p(0))
glVertexAttribPointer(cmo_aVertex, 2, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
cmo_acolor = glGetAttribLocation(self.shader_program, "aColor")
glEnableVertexAttribArray(cmo_acolor)
# Spécifier les attributs de couleur
glVertexAttribPointer(cmo_acolor, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(self.buf_vertices.nbytes))
# Ajouter cette ligne pour activer le mélange des couleurs
glDisable(GL_BLEND)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
# Ajouter cette ligne pour définir l'épaisseur des lignes
glLineWidth(3.0)
glDrawArrays(GL_LINES, 0, len(self.buf_vertices)//2)
# Unbind VAO
glBindVertexArray(0)
# glBindBuffer(GL_ARRAY_BUFFER, 0)
glUseProgram(0)
# wo Shader
# ---------
# glDisable(GL_BLEND)
# glEnableClientState(GL_VERTEX_ARRAY)
# glEnableClientState(GL_COLOR_ARRAY)
# glVertexPointer(2, GL_FLOAT, 0, self.buf_vertices) # 2 vertices per point, 32 bits floats, 0 stride (tightly packed), vertices array
# glColorPointer(3, GL_FLOAT, 0, self.buf_colors)
# glLineWidth(3.0)
# glDrawArrays(GL_LINES, 0, len(self.buf_vertices)//2) # mode, first, count
# # mode in : GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY and GL_PATCHES
# glDisableClientState(GL_VERTEX_ARRAY)
# glDisableClientState(GL_COLOR_ARRAY)
def __del__(self):
""" Delete OpenGL objects """
if self.VAO is not None:
glDeleteVertexArrays(1, [self.VAO])
self.VAO = None
if self.VBO is not None:
glDeleteBuffers(1, [self.VBO])
self.VBO = None
if self.shader_program is not None:
glDeleteProgram(self.shader_program)
[docs]
def _do_kdtree(self):
"""Create kdtree to search nearest neighbor"""
self.mytreeX = cKDTree(self.bordersX['coordscg'].transpose())
self.mytreeY = cKDTree(self.bordersY['coordscg'].transpose())
[docs]
def query_kdtree(self, point:tuple[float,float]):
"""Find nearest border and add to 'selected' dict"""
distX, indexesX = self.mytreeX.query(point)
distY, indexesY = self.mytreeY.query(point)
if distX<distY:
self.bordersX['selected'][indexesX] = ~self.bordersX['selected'][indexesX]
else:
self.bordersY['selected'][indexesY] = ~self.bordersY['selected'][indexesY]
self.update_colors()
return indexesX,indexesY
[docs]
def ray_tracing_numpy(self, poly, XorY:str = 'x'):
"""Find all borders in rectangle or polygon and addto 'selected' dict"""
if XorY.lower()=='x':
x=self.bordersX['coordscg'][0,:]
y=self.bordersX['coordscg'][1,:]
else:
x=self.bordersY['coordscg'][0,:]
y=self.bordersY['coordscg'][1,:]
n = len(poly)
inside = np.zeros(len(x),np.bool_)
p2x = 0.0
p2y = 0.0
xints = 0.0
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
idx = np.nonzero((y > min(p1y,p2y)) & (y <= max(p1y,p2y)) & (x <= max(p1x,p2x)))[0]
if p1y != p2y:
xints = (y[idx]-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x:
inside[idx] = ~inside[idx]
else:
idxx = idx[x[idx] <= xints]
inside[idxx] = ~inside[idxx]
p1x,p1y = p2x,p2y
if XorY.lower()=='x':
self.bordersX['selected']=np.logical_xor(self.bordersX['selected'],inside)
else:
self.bordersY['selected']=np.logical_xor(self.bordersY['selected'],inside)
self.update_colors()
return inside
[docs]
def _find_Str_TypeBC(self,i:int):
"""Convert intBC to nameBC"""
for curbc in self.bc_type:
val_bc, name_bc = curbc.value
if val_bc==i:
return name_bc
[docs]
def _find_Int_TypeBC(self,name:str):
"""Convert nameBC to intBC"""
for curbc in self.bc_type:
val_bc, name_bc = curbc.value
if name_bc==name:
return val_bc
[docs]
def _find_EnumName_TypeBC(self,name:str):
"""Convert nameBC to intBC"""
for curbc in self.bc_type:
val_bc, name_bc = curbc.value
if name_bc==name:
return curbc.name
[docs]
def _find_Enum_TypeBC(self,name:str):
"""Convert nameBC to intBC"""
for curbc in self.bc_type:
val_bc, name_bc = curbc.value
if name_bc==name:
return curbc
[docs]
def get_lists_for_GPU(self) -> tuple[list[boundary_condition_2D], list[boundary_condition_2D]]:
"""
Return list of BC for GPU computing
"""
def create_list_prev(curdict:dict) -> list[boundary_condition_2D]:
list_bc = []
for ij, allbc in curdict.items():
i,j=ij.split('-')
for curname, curval in allbc.items():
if(str(curval) != '99999.0'):
list_bc.append(boundary_condition_2D(int(i),
int(j),
self._find_Int_TypeBC(curname),
float(curval)))
return list_bc
if self._version ==1:
lst_x= create_list_prev(self.bordersX['bc'])
lst_y= create_list_prev(self.bordersY['bc'])
else:
lst_x= create_list_prev(self.bordersX['bc'])
lst_y= create_list_prev(self.bordersY['bc'])
# convert ntype between OO and prev because GPU based on prev
for cur_bc in lst_x:
if cur_bc.ntype == BCType_2D_OO.WATER_LEVEL.value[0]:
cur_bc.ntype = BCType_2D.H.value[0]
elif cur_bc.ntype == BCType_2D_OO.FROUDE_NORMAL.value[0]:
cur_bc.ntype = BCType_2D.FROUDE_NORMAL.value[0]
elif cur_bc.ntype == BCType_2D_OO.NORMAL_DISCHARGE.value[0]:
cur_bc.ntype = BCType_2D.QX.value[0]
elif cur_bc.ntype == BCType_2D_OO.TANGENT_DISCHARGE.value[0]:
cur_bc.ntype = BCType_2D.QY.value[0]
for cur_bc in lst_x:
if cur_bc.ntype == BCType_2D_OO.WATER_LEVEL.value[0]:
cur_bc.ntype = BCType_2D.H.value[0]
elif cur_bc.ntype == BCType_2D_OO.FROUDE_NORMAL.value[0]:
cur_bc.ntype = BCType_2D.FROUDE_NORMAL.value[0]
elif cur_bc.ntype == BCType_2D_OO.NORMAL_DISCHARGE.value[0]:
cur_bc.ntype = BCType_2D.QY.value[0]
elif cur_bc.ntype == BCType_2D_OO.TANGENT_DISCHARGE.value[0]:
cur_bc.ntype = BCType_2D.QX.value[0]
return lst_x, lst_y