[docs]defreplace(self,index,terms,signs):"""Replace the term indicated by ``index`` by ``terms`` of ``signs``. """ifisinstance(terms,(list,tuple)):passelse:terms=[terms,]signs=[signs,]assertlen(terms)==len(signs),f"new terms length is not equal to the length of new signs."for_,signinenumerate(signs):assertsignin('+','-'),f"{_}th sign = {sign} is wrong. Must be '+' or '-'."i,j,k=self._wf._parse_index(index)old_sign=self._wf._sign_dict[i][j][k]ifold_sign=='+':signs_=signselse:signs_=list()fors_insigns:signs_.append(self._switch_sign(s_))signs=signs_new_term_dict=deepcopy(self._wf._ind_dict)# must do deepcopy, use `_ind_dict`, not a typonew_sign_dict=deepcopy(self._wf._ind_dict)# must do deepcopy, use `_ind_dict`, not a typonew_term_dict[i][j][k]=list()new_sign_dict[i][j][k]=list()new_term_dict[i][j][k].extend(terms)new_sign_dict[i][j][k].extend(signs)new_term_dict,new_sign_dict=self._parse_new_weak_formulation_dict(new_term_dict,new_sign_dict)new_wf=self._wf.__class__(self._wf._test_forms,term_sign_dict=[new_term_dict,new_sign_dict])new_wf.unknowns=self._wf.unknowns# pass the unknownsnew_wf._bc=self._wf._bc# pass the bcreturnnew_wf
def_parse_new_weak_formulation_dict(self,new_term_dict,new_sign_dict):""""""term_dict=dict()sign_dict=dict()foriinself._wf._term_dict:term_dict[i]=([],[])sign_dict[i]=([],[])forjinrange(2):forkinrange(len(self._wf._term_dict[i][j])):new_term=new_term_dict[i][j][k]new_sign=new_sign_dict[i][j][k]ifisinstance(new_term,str)andnew_terminself._wf:# this term remain untouched.assertnew_signinself._wf# trivial check._t=self._wf[new_term][1]ifisinstance(new_sign,str)andnew_signinself._wf:sign=self._wf[new_term][0]else:assertnew_signin('+','-'),f"sign must be + or -."sign=new_signterm_dict[i][j].append(_t)sign_dict[i][j].append(sign)else:assertisinstance(new_term,list)and \
isinstance(new_sign,list)and \
len(new_sign)==len(new_term),(f"Whenever we have a "f"modification to a term, pls put it in a list.")forterm,signinzip(new_term,new_sign):ifterm._is_able_to_be_a_weak_term():term_dict[i][j].append(term)sign_dict[i][j].append(sign)else:raiseNotImplementedError()returnterm_dict,sign_dict
[docs]defrearrange(self,rearrangement):"""Rearrange the terms."""ifisinstance(rearrangement,dict):passelifisinstance(rearrangement,(list,tuple)):assertlen(rearrangement)==len(self._wf), \
f"When provide list (or tuple) of rearrangement, we must have a list (or tuple) of length equal to " \
f"amount of equations."rag_dict=dict()fori,raginenumerate(rearrangement):assertisinstance(rag,str)orragisNone, \
f"rearrangement can only be represent by str or None, {i}th rearrangement = {rag} is illegal."rag_dict[i]=ragrearrangement=rag_dictelse:raiseException(f"Rearrangement indicator format wrong.")term_dict=dict()sign_dict=dict()foriinself._wf._term_dict:term_dict[i]=([],[])sign_dict[i]=([],[])foriinrearrangement:assertisinstance(i,int),f"key: {i} is not integer, pls make sure use integer as dict keys."assert0<=i<len(self._wf),f"I cannot find {i}th equation."ri=rearrangement[i]ifriisNoneorri=='':passelse:assertisinstance(ri,str),"Use str to represent a rearrangement pls."if'='notinri:ri+='='else:pass# noinspection PyUnresolvedReferencesleft_terms,right_terms=ri.replace(' ','').split('=')_left_terms=left_terms.replace(',','')_right_terms=right_terms.replace(',','')_=_left_terms+_right_termsassert_.isnumeric(), \
f"rearrangement for {i}th equation: {ri} is illegal, using only comma to separate " \
f"positive indices."left_terms=left_terms.split(',')right_terms=right_terms.split(',')number_terms=len(self._wf._term_dict[i][0])+len(self._wf._term_dict[i][1])ifright_terms==['']andlen(left_terms)<number_terms:# move all rest terms to rightright_terms=list()forminrange(number_terms):ifstr(m)notinleft_terms:right_terms.append(str(m))else:passelifleft_terms==['']andlen(right_terms)<number_terms:# move all rest terms to leftleft_terms=list()forminrange(number_terms):ifstr(m)notinright_terms:left_terms.append(str(m))else:passelse:pass_=list()ifleft_terms!=['']:_.extend(left_terms)else:left_terms=0ifright_terms!=['']:_.extend(right_terms)else:right_terms=0_=[int(__)for__in_]for_i_in_:assert_i_inrange(number_terms), \
f"touching wrong index: {_i_} for equation #{i} whose valid terms ranged({number_terms})."_.sort()_=[str(__)for__in_]assert_==[str(j)forjinrange(number_terms)], \
f'indices of rearrangement for {i}th equation: {ri} are wrong.'ifleft_terms==0:passelse:forkinleft_terms:target_index=str(i)+'-'+ksign,target_term=self._wf[target_index]iftarget_term==0:continueelse:_j=self._wf._parse_index(target_index)[1]if_j==0:# the target term is also at left.passelif_j==1:# the target term is at opposite side, i.e., rightsign=self._switch_sign(sign)else:raiseException()term_dict[i][0].append(target_term)sign_dict[i][0].append(sign)ifright_terms==0:passelse:forminright_terms:target_index=str(i)+'-'+msign,target_term=self._wf[target_index]iftarget_term==0:continueelse:_j=self._wf._parse_index(target_index)[1]if_j==0:# the target term is at opposite side, i.e., leftsign=self._switch_sign(sign)elif_j==1:# the target term is also at right.passelse:raiseException()term_dict[i][1].append(target_term)sign_dict[i][1].append(sign)for_iinself._wf._term_dict:if_inotinrearrangementorrearrangement[_i]isNoneorrearrangement[_i]=='':term_dict[_i]=self._wf._term_dict[_i]sign_dict[_i]=self._wf._sign_dict[_i]else:passnew_wf=self._wf.__class__(self._wf._test_forms,term_sign_dict=[term_dict,sign_dict])new_wf.unknowns=self._wf.unknowns# pass the unknownsnew_wf._bc=self._wf._bc# pass the bcreturnnew_wf
[docs]defswitch_sign(self,rows):"""Switch the signs of all terms of equations ``rows``"""ifisinstance(rows,int):rows=[rows,]else:assertisinstance(rows,(list,tuple)),f"put rows in a list or tuple."rows=[int(_)for_inrows]forrowinrows:assert0<=row<len(self._wf),rf"row={row} is wrong."new_sign_dict=dict()foriinself._wf._term_dict:ifinotinrows:new_sign_dict[i]=self._wf._sign_dict[i]else:new_sign_dict[i]=([],[])old_signs=self._wf._sign_dict[i]left_signs,right_signs=old_signsforsigninleft_signs:new_sign_dict[i][0].append(self._switch_sign(sign))forsigninright_signs:new_sign_dict[i][1].append(self._switch_sign(sign))new_wf=self._wf.__class__(self._wf._test_forms,term_sign_dict=[self._wf._term_dict,new_sign_dict])new_wf.unknowns=self._wf.unknowns# pass the unknownsnew_wf._bc=self._wf._bc# pass the bcreturnnew_wf
[docs]defintegration_by_parts(self,index):"""Do integration by parts for the term indicated by ``index``."""term=self._wf[index][1]terms,signs=term._integration_by_parts()returnself.replace(index,terms,signs)
[docs]defsplit(self,index,*args,**kwargs):"""Split the term indicated by ``index`` into multiple terms."""term=self._wf[index][1]terms,signs=term.split(*args,**kwargs)returnself.replace(index,terms,signs)
[docs]defdelete(self,index):"""Delete the term indicated by ``index``."""wf=self.replace(index,[],[])returnwf