132 Convert STR%VAR into single local variable contained in compute (a-stmt)
133 and in if-then-stmt, else-if-stmt, where-stmt
135 ZA = 1 + CST%XG ==> ZA = 1 + XCST_G
136 ZA = 1 + PARAM_ICE%XRTMIN(3) ==> ZA = 1 + XPARAM_ICE_XRTMIN3
137 ZRSMIN(1:KRR) = ICED%XRTMIN(1:KRR) => ZRSMIN(1:KRR) = ICEDXRTMIN1KRR(1:KRR)
138 IF(TURBN%CSUBG_MF_PDF=='NONE')THEN => IF(CTURBNSUBG_MF_PDF=='NONE')THEN
140 RESTRICTION : works only if the r-component variable is contained in 1 parent structure.
141 Allowed for conversion : CST%XG
142 Not converted : TOTO%CST%XG (for now, recursion must be coded)
143 Not converted : TOTO%ARRAY(:) (shape of the array must be determined from E1)
145 def convertOneType(component, newVarList, scope):
147 objType = scope.getParent(component, 2)
148 objTypeStr = alltext(objType).upper()
149 namedENn = objType.find(
'.//{*}N/{*}n')
150 structure = namedENn.text
151 variable = component.find(
'.//{*}ct').text.upper()
155 arrayRall = objType.findall(
'.//{*}array-R')
156 if len(arrayRall) > 0:
157 arrayR = copy.deepcopy(arrayRall[0])
158 txt = alltext(arrayR).replace(
',',
'')
159 txt = txt.replace(
':',
'')
160 txt = txt.replace(
'(',
'')
161 txt = txt.replace(
')',
'')
162 arrayIndices = arrayIndices + txt
163 elif len(objType.findall(
'.//{*}element-LT')) > 0:
165 for elem
in objType.findall(
'.//{*}element'):
166 arrayIndices = arrayIndices + alltext(elem)
167 newName = variable[0] + structure + variable[1:] + arrayIndices
168 newName = newName.upper()
172 namedENn.text = newName
173 objType.remove(objType.find(
'.//{*}R-LT'))
174 if len(arrayRall) > 0:
175 objType.insert(1, arrayR)
178 if newName
not in newVarList:
179 if len(arrayRall) == 0:
180 newVarList[newName] = (
None, objTypeStr)
182 newVarList[newName] = (arrayR, objTypeStr)
184 scopes = self.getScopes()
185 if scopes[0].path.split(
'/')[-1].split(
':')[1][:4] ==
'MODD':
187 for scope
in [scope
for scope
in scopes
188 if 'sub:' in scope.path
and 'interface' not in scope.path]:
190 for ifStmt
in (scope.findall(
'.//{*}if-then-stmt') +
191 scope.findall(
'.//{*}else-if-stmt') +
192 scope.findall(
'.//{*}where-stmt')):
193 compo = ifStmt.findall(
'.//{*}component-R')
195 for elcompo
in compo:
196 convertOneType(elcompo, newVarList, scope)
198 for aStmt
in scope.findall(
'.//{*}a-stmt'):
201 if len(aStmt[0].findall(
'.//{*}component-R')) == 0:
202 compoE2 = aStmt.findall(
'.//{*}component-R')
209 nbNamedEinE2 = len(aStmt.findall(
'.//{*}E-2')[0].findall(
'.//{*}named-E/' +
211 if nbNamedEinE2 > 1
or nbNamedEinE2 == 1
and \
212 len(aStmt[0].findall(
'.//{*}R-LT')) == 1:
213 for elcompoE2
in compoE2:
214 convertOneType(elcompoE2, newVarList, scope)
217 for el, var
in newVarList.items():
218 if el[0].upper() ==
'X' or el[0].upper() ==
'P' or el[0].upper() ==
'Z':
220 elif el[0].upper() ==
'L' or el[0].upper() ==
'O':
222 elif el[0].upper() ==
'N' or el[0].upper() ==
'I' or el[0].upper() ==
'K':
224 elif el[0].upper() ==
'C':
225 varType =
'CHARACTER(LEN=LEN(' + var[1] +
'))'
227 raise PYFTError(
'Case not implemented for the first letter of the newVarName' +
228 el +
' in convertTypesInCompute')
232 varArray =
', DIMENSION('
233 for i, sub
in enumerate(var[0].findall(
'.//{*}section-subscript')):
234 if len(sub.findall(
'.//{*}upper-bound')) > 0:
235 dimSize = simplifyExpr(
236 alltext(sub.findall(
'.//{*}upper-bound')[0]) +
237 '-' + alltext(sub.findall(
'.//{*}lower-bound')[0]) +
239 elif len(sub.findall(
'.//{*}lover-bound')) > 0:
240 dimSize = simplifyExpr(alltext(sub.findall(
'.//{*}lower-bound')[0]))
242 dimSize =
'SIZE(' + var[1] +
',' + str(i+1) +
')'
243 varArray =
', DIMENSION(' + dimSize +
','
244 varArray = varArray[:-1] +
')'
245 scope.addVar([[scope.path, el, varType + varArray +
' :: ' + el,
None]])
248 stmtAffect = createExpr(el +
"=" + var[1])[0]
249 scope.insertStatement(scope.indent(stmtAffect), first=
True)
318 Add MPPDB_CHEKS on all intent REAL arrays on subroutines.
319 ****** Not applied on modd_ routines. ********
320 Handle optional arguments.
321 Example, for a BL89 routine with 4 arguments, 1 INTENT(IN),
322 2 INTENT(INOUT), 1 INTENT(OUT), it produces :
323 IF (MPPDB_INITIALIZED) THEN
325 CALL MPPDB_CHECK(PZZ, "BL89 beg:PZZ")
326 !Check all INOUT arrays
327 CALL MPPDB_CHECK(PDZZ, "BL89 beg:PDZZ")
328 CALL MPPDB_CHECK(PTHVREF, "BL89 beg:PTHVREF")
331 IF (MPPDB_INITIALIZED) THEN
332 !Check all INOUT arrays
333 CALL MPPDB_CHECK(PDZZ, "BL89 end:PDZZ")
334 CALL MPPDB_CHECK(PTHVREF, "BL89 end:PTHVREF")
335 !Check all OUT arrays
336 CALL MPPDB_CHECK(PLM, "BL89 end:PLM")
338 param printsMode: if True, instead of CALL MPPDB_CHECK, add fortran prints for debugging
340 def addPrints_statement(var, typeofPrints='minmax'):
341 ifBeg, ifEnd =
'',
''
344 if typeofPrints ==
'minmax':
345 strMSG = f
'MINMAX {varName} = \",MINVAL({varName}), MAXVAL({varName})'
346 elif typeofPrints ==
'shape':
347 strMSG = f
'SHAPE {varName} = \",SHAPE({varName})'
349 raise PYFTError(
'typeofPrints is either minmax or shape in addPrints_statement')
351 strMSG = var[
'n'] +
' = \",' + var[
'n']
353 ifBeg = ifBeg +
'IF (PRESENT(' + var[
'n'] +
')) THEN\n '
354 ifEnd = ifEnd +
'\nEND IF'
355 return createExpr(ifBeg +
"print*,\"" + strMSG + ifEnd)[0]
357 def addMPPDB_CHECK_statement(var, subRoutineName, strMSG='beg:
'):
358 ifBeg, ifEnd, addD, addLastDim, addSecondDimType = '',
'',
'',
'',
''
362 if 'D%NIJT' in var[
'as'][0][1]:
364 if len(var[
'as']) == 2:
366 addLastDim =
', ' + var[
'as'][1][1]
367 if len(var[
'as']) >= 2:
370 if 'D%NK' in var[
'as'][1][1]:
371 addSecondDimType =
',' +
'''"VERTICAL"'''
373 addSecondDimType =
',' +
'''"OTHER"'''
374 if 'MERGE' in var[
'as'][-1][1]:
375 keyDimMerge = var[
'as'][-1][1].split(
',')[2][:-1]
376 ifBeg =
'IF (' + keyDimMerge +
') THEN\n'
379 ifBeg = ifBeg +
'IF (PRESENT(' + var[
'n'] +
')) THEN\n IF (SIZE(' + \
380 var[
'n'] +
',1) > 0) THEN\n'
381 ifEnd = ifEnd +
'\nEND IF\nEND IF'
382 argsMPPDB = var[
'n'] +
", " +
"\"" + subRoutineName +
" " + strMSG+var[
'n'] +
"\""
383 return createExpr(ifBeg +
"CALL MPPDB_CHECK(" + addD + argsMPPDB +
384 addLastDim + addSecondDimType +
")" + ifEnd)[0]
385 scopes = self.getScopes()
386 if scopes[0].path.split(
'/')[-1].split(
':')[1][:4] ==
'MODD':
393 if 'sub:' in scope.path
and 'func' not in scope.path
and 'interface' not in scope.path:
394 subRoutineName = scope.path.split(
'/')[-1].split(
':')[1]
397 arraysIn, arraysInOut, arraysOut = [], [], []
399 for var
in scope.varList:
400 if var[
'arg']
and var[
'as']
and 'TYPE' not in var[
't']
and \
401 'REAL' in var[
't']
and var[
'scopePath'] == scope.path:
404 if var[
'i'] ==
'INOUT':
405 arraysInOut.append(var)
406 if var[
'i'] ==
'OUT':
407 arraysOut.append(var)
409 for var
in scope.varList:
410 if not var[
't']
or var[
't']
and 'TYPE' not in var[
't']:
413 if var[
'i'] ==
'INOUT':
414 arraysInOut.append(var)
415 if var[
'i'] ==
'OUT':
416 arraysOut.append(var)
418 if len(arraysIn) + len(arraysInOut) + len(arraysOut) == 0:
423 scope.addModuleVar([(scope.path,
'MODE_MPPDB',
None)])
425 scope.addModuleVar([(scope.path,
'MODD_BLANK_n', [
'LDUMMY1'])])
428 commentIN = createElem(
'C', text=
'!Check all IN arrays', tail=
'\n')
429 commentINOUT = createElem(
'C', text=
'!Check all INOUT arrays', tail=
'\n')
430 commentOUT = createElem(
'C', text=
'!Check all OUT arrays', tail=
'\n')
433 if len(arraysIn) + len(arraysInOut) > 0:
435 ifMPPDBinit = createExpr(
"IF (MPPDB_INITIALIZED) THEN\n END IF")[0]
437 ifMPPDBinit = createExpr(
"IF (LDUMMY1) THEN\n END IF")[0]
438 ifMPPDB = ifMPPDBinit.find(
'.//{*}if-block')
441 if len(arraysIn) > 0:
442 ifMPPDB.insert(1, commentIN)
443 for i, var
in enumerate(arraysIn):
445 ifMPPDB.insert(2 + i, addMPPDB_CHECK_statement(var, subRoutineName,
448 ifMPPDB.insert(2 + i, addPrints_statement(var,
449 typeofPrints=
'minmax'))
450 ifMPPDB.insert(3 + i, addPrints_statement(var,
451 typeofPrints=
'shape'))
454 if len(arraysInOut) > 0:
455 shiftLineNumber = 2
if len(arraysIn) > 0
else 1
457 ifMPPDB.insert(len(arraysIn) + shiftLineNumber, commentINOUT)
459 ifMPPDB.insert(len(arraysIn)*2 + shiftLineNumber-1, commentINOUT)
461 for i, var
in enumerate(arraysInOut):
463 ifMPPDB.insert(len(arraysIn) + shiftLineNumber + 1 + i,
464 addMPPDB_CHECK_statement(var, subRoutineName,
467 ifMPPDB.insert(len(arraysIn) + shiftLineNumber + 1 + i,
468 addPrints_statement(var, typeofPrints=
'minmax'))
471 scope.insertStatement(scope.indent(ifMPPDBinit), first=
True)
474 if len(arraysInOut) + len(arraysOut) > 0:
476 ifMPPDBend = createExpr(
"IF (MPPDB_INITIALIZED) THEN\n END IF")[0]
478 ifMPPDBend = createExpr(
"IF (LDUMMY1) THEN\n END IF")[0]
479 ifMPPDB = ifMPPDBend.find(
'.//{*}if-block')
482 if len(arraysInOut) > 0:
483 ifMPPDB.insert(1, commentINOUT)
484 for i, var
in enumerate(arraysInOut):
486 ifMPPDB.insert(2 + i, addMPPDB_CHECK_statement(var, subRoutineName,
489 ifMPPDB.insert(2 + i, addPrints_statement(var,
490 typeofPrints=
'minmax'))
493 if len(arraysOut) > 0:
494 shiftLineNumber = 2
if len(arraysInOut) > 0
else 1
496 ifMPPDB.insert(len(arraysInOut) + shiftLineNumber, commentOUT)
498 ifMPPDB.insert(len(arraysInOut)*2 + shiftLineNumber-1, commentOUT)
499 for i, var
in enumerate(arraysOut):
501 ifMPPDB.insert(len(arraysInOut) + shiftLineNumber + 1 + i,
502 addMPPDB_CHECK_statement(var, subRoutineName,
505 ifMPPDB.insert(len(arraysInOut) + shiftLineNumber + 1 + i,
506 addPrints_statement(var, typeofPrints=
'minmax'))
509 scope.insertStatement(scope.indent(ifMPPDBend), first=
False)
617 def removeIJDim(self, stopScopes, parser=None, parserOptions=None, wrapH=False, simplify=False):
619 Transform routines to be called in a loop on columns
620 :param stopScopes: scope paths where we stop to add the D argument (if needed)
621 :param parser, parserOptions, wrapH: see the PYFT class
622 :param simplify: try to simplify code (remove useless dimensions in call)
624 ComputeInSingleColumn :
625 - Remove all Do loops on JI and JJ
626 - Initialize former indexes JI, JJ, JIJ to first array element:
627 JI=D%NIB, JJ=D%NJB, JIJ=D%NIJB
628 - If simplify is True, replace (:,*) on I/J/IJ dimension on argument
629 with explicit (:,*) on CALL statements:
630 e.g. CALL FOO(D, A(:,JK,1), B(:,:))
631 ==> CALL FOO(D, A(JIJ,JK,1), B(:,:)) only if the target argument is not an array
634 indexToCheck = {
'JI': (
'D%NIB',
'D%NIT'),
635 'JJ': (
'D%NJB',
'D%NJT'),
636 'JIJ': (
'D%NIJB',
'D%NIJT')}
638 def slice2index(namedE, scope):
640 Transform a slice on the horizontal dimension into an index
641 Eg.: X(1:D%NIJT, 1:D%NKT) => X(JIJ, 1:D%NKT) Be careful, this array is not contiguous.
642 X(1:D%NIJT, JK) => X(JIJ, JK)
643 :param namedE: array to transform
644 :param scope: scope where the array is
647 for isub, sub
in enumerate(namedE.findall(
'./{*}R-LT/{*}array-R/' +
648 '{*}section-subscript-LT/' +
649 '{*}section-subscript')):
650 if ':' in alltext(sub):
651 loopIndex, _, _ = scope.findIndexArrayBounds(namedE, isub, _loopVarPHYEX)
652 if loopIndex
in indexToCheck:
655 lowerBound = createElem(
'lower-bound')
656 sub.insert(0, lowerBound)
658 lowerBound = sub.find(
'./{*}lower-bound')
660 for item
in lowerBound:
661 lowerBound.remove(item)
662 upperBound = sub.find(
'./{*}upper-bound')
663 if upperBound
is not None:
664 sub.remove(upperBound)
665 lowerBound.append(createExprPart(loopIndex))
666 if loopIndex
not in indexRemoved:
667 indexRemoved.append(loopIndex)
670 if ':' not in alltext(namedE.find(
'./{*}R-LT/{*}array-R/{*}section-subscript-LT')):
671 namedE.find(
'./{*}R-LT/{*}array-R').tag = f
'{{{NAMESPACE}}}parens-R'
672 namedE.find(
'./{*}R-LT/{*}parens-R/' +
673 '{*}section-subscript-LT').tag = f
'{{{NAMESPACE}}}element-LT'
674 for ss
in namedE.findall(
'./{*}R-LT/{*}parens-R/' +
675 '{*}element-LT/{*}section-subscript'):
676 ss.tag = f
'{{{NAMESPACE}}}element'
677 lowerBound = ss.find(
'./{*}lower-bound')
678 for item
in lowerBound:
680 ss.remove(lowerBound)
683 self.addArrayParentheses()
686 self.attachArraySpecToEntity()
687 hUupperBounds = [v[1]
for v
in indexToCheck.values()]
691 for scope
in [scope
for scope
in self.getScopes()[::-1]
692 if 'func:' not in scope.path
and
693 (scope.path
in stopScopes
or
694 self.tree.isUnderStopScopes(scope.path, stopScopes,
695 includeInterfaces=
True))]:
701 for doNode
in scope.findall(
'.//{*}do-construct')[::-1]:
702 for loopI
in doNode.findall(
'./{*}do-stmt/{*}do-V/{*}named-E/{*}N'):
703 loopIname = n2name(loopI).upper()
704 if loopIname
in indexToCheck:
707 par = scope.getParent(doNode)
708 index = list(par).index(doNode)
709 for item
in doNode[1:-1][::-1]:
710 par.insert(index, item)
712 if loopIname
not in indexRemoved:
713 indexRemoved.append(loopIname)
718 for intr
in scope.findall(
'.//{*}R-LT/{*}parens-R/../..'):
719 intrName = n2name(intr.find(
'./{*}N')).upper()
720 if intrName
in (
'PACK',
'UNPACK',
'COUNT',
'MAXVAL',
'MINVAL',
'ALL',
'ANY',
'SUM'):
728 while par
is not None and not isStmt(par):
729 par = scope.getParent(par)
730 if tag(par)
in (
'a-stmt',
'op-E'):
735 for namedE
in parToUse.findall(
'.//{*}R-LT/{*}array-R/../..'):
736 slice2index(namedE, scope)
739 if intr.find(
'.//{*}R-LT/{*}array-R')
is None:
740 if intrName
in (
'MAXVAL',
'MINVAL',
'SUM',
'ALL',
'ANY'):
742 parens = intr.find(
'./{*}R-LT/{*}parens-R')
743 parens.tag = f
'{{{NAMESPACE}}}parens-E'
744 intrPar = scope.getParent(intr)
745 intrPar.insert(list(intrPar).index(intr), parens)
747 elif intrName ==
'COUNT':
749 nodeN = intr.find(
'./{*}N')
750 for item
in nodeN[1:]:
752 nodeN.find(
'./{*}n').text =
'MERGE'
753 elementLT = intr.find(
'./{*}R-LT/{*}parens-R/{*}element-LT')
755 element = createElem(
'element', tail=
', ')
756 element.append(createExprPart(val))
757 elementLT.insert(0, element)
770 assert scope.find(
'.//{*}include')
is None and \
771 scope.find(
'.//{*}include-stmt')
is None, \
772 "inlining must be performed before removing horizontal dimensions"
774 if scope.path
in stopScopes:
776 preserveShape = [v[
'n']
for v
in scope.varList
if v[
'arg']]
781 if 'sub:' in scope.path:
785 for namedE
in scope.findall(
'.//{*}named-E/{*}R-LT/{*}parens-R/../..'):
786 if n2name(namedE.find(
'./{*}N')).upper()
not in preserveShape:
787 var = scope.varList.findVar(n2name(namedE.find(
'./{*}N')).upper())
788 if var
is not None and var[
'as']
is not None and len(var[
'as']) > 0:
789 subs = namedE.findall(
'./{*}R-LT/{*}parens-R/' +
790 '{*}element-LT/{*}element')
791 if (len(subs) == 1
and var[
'as'][0][1]
in hUupperBounds)
or \
792 (len(subs) == 2
and (var[
'as'][0][1]
in hUupperBounds
and
793 var[
'as'][1][1]
in hUupperBounds)):
794 namedE.remove(namedE.find(
'./{*}R-LT'))
798 for call
in scope.findall(
'.//{*}call-stmt'):
799 for namedE
in call.findall(
'./{*}arg-spec//{*}named-E'):
800 subs = namedE.findall(
'.//{*}section-subscript')
801 var = scope.varList.findVar(n2name(namedE.find(
'./{*}N')).upper())
802 if len(subs) > 0
and (var
is None or var[
'as']
is None or
803 len(var[
'as']) < len(subs)):
811 elif (len(subs) >= 2
and
812 ':' in alltext(subs[0])
and var[
'as'][0][1]
in hUupperBounds
and
813 ':' in alltext(subs[1])
and var[
'as'][1][1]
in hUupperBounds):
815 remove = len(subs) == 2
816 index = (len(subs) > 2
and
817 len([sub
for sub
in subs
if ':' in alltext(sub)]) == 2)
818 elif (len(subs) >= 1
and
819 ':' in alltext(subs[0])
and var[
'as'][0][1]
in hUupperBounds):
821 remove = len(subs) == 1
822 index = (len(subs) > 1
and
823 len([sub
for sub
in subs
if ':' in alltext(sub)]) == 1)
828 if n2name(namedE.find(
'./{*}N')).upper()
in preserveShape:
829 slice2index(namedE, scope)
831 nodeRLT = namedE.find(
'.//{*}R-LT')
832 scope.getParent(nodeRLT).remove(nodeRLT)
834 slice2index(namedE, scope)
839 for decl
in scope.findall(
'.//{*}T-decl-stmt/{*}EN-decl-LT/{*}EN-decl'):
840 name = n2name(decl.find(
'./{*}EN-N/{*}N')).upper()
841 if name
not in preserveShape:
842 varsShape = decl.findall(
'.//{*}shape-spec-LT')
843 for varShape
in varsShape:
844 subs = varShape.findall(
'.//{*}shape-spec')
845 if (len(subs) == 1
and alltext(subs[0])
in hUupperBounds)
or \
846 (len(subs) == 2
and (alltext(subs[0])
in hUupperBounds
and
847 alltext(subs[1])
in hUupperBounds)):
849 itemToRemove = scope.getParent(varShape)
850 scope.getParent(itemToRemove).remove(itemToRemove)
855 for loopIndex
in indexRemoved:
858 scope.insertStatement(
859 createExpr(loopIndex +
" = " + indexToCheck[loopIndex][0])[0],
True)
860 if len(indexRemoved) > 0:
861 scope.addArgInTree(
'D',
'TYPE(DIMPHYEX_t) :: D',
862 0, stopScopes, moduleVarList=[(
'MODD_DIMPHYEX', [
'DIMPHYEX_t'])],
863 parser=parser, parserOptions=parserOptions, wrapH=wrapH)
865 scope.addVar([[scope.path, loopIndex,
'INTEGER :: ' + loopIndex,
None]
866 for loopIndex
in indexRemoved
867 if scope.varList.findVar(loopIndex, exactScope=
True)
is None])
926 Convert intrinsic math functions **, LOG, ATAN, **2, **3, **4, EXP, COS, SIN, ATAN2
927 into a self defined function BR_ for MesoNH CPU/GPU bit-reproductibility
930 powerBRList = [2, 3, 4]
931 mathBRList = [
'ALOG',
'LOG',
'EXP',
'COS',
'SIN',
'ASIN',
'ATAN',
'ATAN2']
933 for scope
in self.getScopes():
942 for opo
in scope.findall(
'.//{*}o'):
943 if alltext(opo) ==
'**':
944 op = scope.getParent(opo)
945 opE = scope.getParent(opo, level=2)
946 parOfopE = scope.getParent(opo, level=3)
948 index = list(parOfopE).index(opE)
952 rightOfPow = scope.getSiblings(op, after=
True, before=
False)[0]
953 leftOfPow = scope.getSiblings(op, after=
False, before=
True)[0]
956 nodeRLT = createElem(
'R-LT')
957 parensR = createElem(
'parens-R', text=
'(', tail=
')')
958 elementLT = createElem(
'element-LT')
962 if tag(rightOfPow) ==
'literal-E':
964 powerNumber = int(alltext(rightOfPow).replace(
'.',
''))
965 if powerNumber
in powerBRList:
980 nodeBRP = createExprPart(
'BR_P' + str(powerNumber))
981 element = createElem(
'element')
982 element.append(leftOfPow)
983 elementLT.append(element)
986 if tag(rightOfPow) !=
'literal-E' or \
987 (tag(rightOfPow) ==
'literal-E' and
988 int(alltext(rightOfPow).replace(
'.',
''))
not in powerBRList):
1006 nodeBRP = createExprPart(
'BR_POW')
1007 leftElement = createElem(
'element', tail=
',')
1008 leftElement.append(leftOfPow)
1009 rightElement = createElem(
'element')
1010 rightElement.append(rightOfPow)
1011 elementLT.append(leftElement)
1012 elementLT.append(rightElement)
1016 parensR.append(elementLT)
1017 nodeRLT.append(parensR)
1018 nodeBRP.insert(1, nodeRLT)
1019 nodeBRP.tail = opE.tail
1020 parOfopE.remove(opE)
1021 parOfopE.insert(index, nodeBRP)
1024 scope.addModuleVar([(scope.path,
'MODI_BITREP',
None)])
1027 for nnn
in scope.findall(
'.//{*}named-E/{*}N/{*}n'):
1028 if alltext(nnn).upper()
in mathBRList:
1029 if alltext(nnn).upper() ==
'ALOG':
1032 nnn.text =
'BR_' + nnn.text
1034 scope.addModuleVar([(scope.path,
'MODI_BITREP',
None)])
1039 Convert all calling of functions and gradient present in shumansGradients
1040 table into the use of subroutines
1041 and use mnh_expand_directives to handle intermediate computations
1043 def getDimsAndMNHExpandIndexes(zshugradwkDim, dimWorkingVar=''):
1045 if zshugradwkDim == 1:
1046 dimSuffRoutine =
'2D'
1048 mnhExpandArrayIndexes =
'JIJ=IIJB:IIJE'
1049 elif zshugradwkDim == 2:
1051 if 'D%NKT' in dimWorkingVar:
1052 mnhExpandArrayIndexes =
'JIJ=IIJB:IIJE,JK=1:IKT'
1053 elif 'D%NIT' in dimWorkingVar
and 'D%NJT' in dimWorkingVar:
1055 mnhExpandArrayIndexes =
'JI=1:IIT,JJ=1:IJT'
1056 dimSuffRoutine =
'2D'
1062 mnhExpandArrayIndexes =
'JIJ=IIJB:IIJE,JK=1:IKT'
1063 elif zshugradwkDim == 3:
1065 mnhExpandArrayIndexes =
'JI=1:IIT,JJ=1:IJT,JK=1:IKT'
1067 raise PYFTError(
'Shuman func to routine conversion not implemented ' +
1068 'for 4D+ dimensions variables')
1069 return dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes
1071 def FUNCtoROUTINE(scope, stmt, itemFuncN, localShumansCount, inComputeStmt,
1072 nbzshugradwk, zshugradwkDim, dimWorkingVar):
1074 :param scope: node on which the calling function is present before transformation
1075 :param stmt: statement node (a-stmt or call-stmt) that contains the function(s) to be
1077 :param itemFuncN: <n>FUNCTIONNAME</n> node
1078 :param localShumansCount: instance of the shumansGradients dictionnary
1079 for the given scope (which contains the number of times a
1080 function has been called within a transformation)
1081 :param dimWorkingVar: string of the declaration of a potential working variable
1082 depending on the array on wich the shuman is applied
1083 (e.g. MZM(PRHODJ(:,IKB));
1084 dimWorkingVar = 'REAL, DIMENSION(D%NIJT) :: ' )
1086 :return callStmt: the new CALL to the routines statement
1087 :return computeStmt: the a-stmt computation statement if there was an operation
1088 in the calling function in stmt
1091 parStmt = scope.getParent(stmt)
1092 parItemFuncN = scope.getParent(itemFuncN)
1094 grandparItemFuncN = scope.getParent(itemFuncN, level=2)
1095 funcName = alltext(itemFuncN)
1098 indexForCall = list(parStmt).index(stmt)
1103 siblsItemFuncN = scope.getSiblings(parItemFuncN, after=
True, before=
False)
1104 workingItem = siblsItemFuncN[0][0][0]
1107 if len(siblsItemFuncN[0][0]) > 1:
1109 workingItem = scope.updateContinuation(siblsItemFuncN[0][0], removeALL=
True,
1110 align=
False, addBegin=
False)[0]
1114 opE = workingItem.findall(
'.//{*}op-E')
1115 scope.addArrayParenthesesInNode(workingItem)
1117 dimSuffVar = str(zshugradwkDim) +
'D'
1118 dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes = \
1119 getDimsAndMNHExpandIndexes(zshugradwkDim, dimWorkingVar)
1122 computingVarName =
'ZSHUGRADWK'+str(nbzshugradwk)+
'_'+str(zshugradwkDim)+
'D'
1124 if not scope.varList.findVar(computingVarName):
1125 scope.addVar([[scope.path, computingVarName,
1126 dimWorkingVar + computingVarName,
None]])
1130 computeVar = scope.varList.findVar(computingVarName)
1131 dimWorkingVar =
'REAL, DIMENSION('
1132 for dims
in computeVar[
'as'][:arrayDim]:
1133 dimWorkingVar += dims[1] +
','
1134 dimWorkingVar = dimWorkingVar[:-1] +
') ::'
1136 dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes = \
1137 getDimsAndMNHExpandIndexes(zshugradwkDim, dimWorkingVar)
1140 mnhOpenDir =
"!$mnh_expand_array(" + mnhExpandArrayIndexes +
")"
1141 mnhCloseDir =
"!$mnh_end_expand_array(" + mnhExpandArrayIndexes +
")"
1142 computeStmt = createExpr(computingVarName +
" = " + alltext(workingItem))[0]
1143 workingItem = computeStmt.find(
'.//{*}E-1')
1144 parStmt.insert(indexForCall, createElem(
'C', text=
'!$acc kernels', tail=
'\n'))
1145 parStmt.insert(indexForCall + 1, createElem(
'C', text=mnhOpenDir, tail=
'\n'))
1146 parStmt.insert(indexForCall + 2, computeStmt)
1147 parStmt.insert(indexForCall + 3, createElem(
'C', text=mnhCloseDir, tail=
'\n'))
1148 parStmt.insert(indexForCall + 4, createElem(
'C',
1149 text=
'!$acc end kernels', tail=
'\n'))
1150 parStmt.insert(indexForCall + 5, createElem(
'C',
1151 text=
'!', tail=
'\n'))
1155 if zshugradwkDim == 1:
1156 dimSuffRoutine =
'2D'
1157 workingVar =
'Z' + funcName + dimSuffVar +
'_WORK' + str(localShumansCount[funcName])
1158 gpuGradientImplementation =
'_PHY(D, '
1159 if funcName
in (
'GY_U_UV',
'GX_V_UV'):
1160 gpuGradientImplementation =
'_DEVICE('
1161 callStmt = createExpr(
"CALL " + funcName + dimSuffRoutine +
1162 gpuGradientImplementation + alltext(workingItem) +
1163 ", " + workingVar +
")")[0]
1164 parStmt.insert(indexForCall, callStmt)
1167 parOfgrandparItemFuncN = scope.getParent(grandparItemFuncN)
1168 indexWorkingVar = list(parOfgrandparItemFuncN).index(grandparItemFuncN)
1169 savedTail = grandparItemFuncN.tail
1170 parOfgrandparItemFuncN.remove(grandparItemFuncN)
1173 xmlWorkingvar = createExprPart(workingVar)
1174 xmlWorkingvar.tail = savedTail
1175 parOfgrandparItemFuncN.insert(indexWorkingVar, xmlWorkingvar)
1178 if not scope.varList.findVar(workingVar):
1179 scope.addVar([[scope.path, workingVar, dimWorkingVar + workingVar,
None]])
1181 return callStmt, computeStmt, nbzshugradwk
1183 shumansGradients = {
'MZM': 0,
'MXM': 0,
'MYM': 0,
'MZF': 0,
'MXF': 0,
'MYF': 0,
1184 'DZM': 0,
'DXM': 0,
'DYM': 0,
'DZF': 0,
'DXF': 0,
'DYF': 0,
1185 'GZ_M_W': 0,
'GZ_W_M': 0,
'GZ_U_UW': 0,
'GZ_V_VW': 0,
1186 'GX_M_U': 0,
'GX_U_M': 0,
'GX_W_UW': 0,
'GX_M_M': 0,
1187 'GY_V_M': 0,
'GY_M_V': 0,
'GY_W_VW': 0,
'GY_M_M': 0,
1188 'GX_V_UV': 0,
'GY_U_UV': 0}
1189 scopes = self.getScopes()
1190 if scopes[0].path.split(
'/')[-1].split(
':')[1][:4] ==
'MODD':
1192 for scope
in scopes:
1193 if 'sub:' in scope.path
and 'func' not in scope.path \
1194 and 'interface' not in scope.path:
1197 foundStmtandCalls, computeStmtforParenthesis = {}, []
1198 aStmt = scope.findall(
'.//{*}a-stmt')
1199 callStmts = scope.findall(
'.//{*}call-stmt')
1200 aStmtandCallStmts = aStmt + callStmts
1201 for stmt
in aStmtandCallStmts:
1202 elemN = stmt.findall(
'.//{*}n')
1204 if alltext(el)
in list(shumansGradients):
1207 parStmt = scope.getParent(stmt)
1208 if tag(parStmt) ==
'action-stmt':
1209 scope.changeIfStatementsInIfConstructs(
1210 singleItem=scope.getParent(parStmt))
1212 if str(stmt)
in foundStmtandCalls:
1213 foundStmtandCalls[str(stmt)][1] += 1
1215 foundStmtandCalls[str(stmt)] = [stmt, 1]
1218 for stmt
in foundStmtandCalls:
1219 localShumansGradients = copy.deepcopy(shumansGradients)
1220 elemToLookFor = [foundStmtandCalls[stmt][0]]
1221 previousComputeStmt = []
1224 while len(elemToLookFor) > 0:
1226 for elem
in elemToLookFor:
1227 elemN = elem.findall(
'.//{*}n')
1229 if alltext(el)
in list(localShumansGradients.keys()):
1234 nodeE1var = foundStmtandCalls[stmt][0].findall(
1235 './/{*}E-1/{*}named-E/{*}N')
1236 if len(nodeE1var) > 0:
1237 var = scope.varList.findVar(alltext(nodeE1var[0]))
1238 allSubscripts = foundStmtandCalls[stmt][0].findall(
1239 './/{*}E-1//{*}named-E/{*}R-LT/' +
1240 '{*}array-R/{*}section-subscript-LT')
1244 elPar = scope.getParent(el, level=2)
1245 callVar = elPar.findall(
'.//{*}named-E/{*}N')
1246 if alltext(el)[0] ==
'G':
1251 var = scope.varList.findVar(alltext(callVar[-1]))
1252 shumanIsCalledOn = scope.getParent(callVar[-1])
1255 var, inested =
None, 0
1257 while not var
or len(var[
'as']) == 0:
1261 var = scope.varList.findVar(
1262 alltext(callVar[inested]))
1264 shumanIsCalledOn = scope.getParent(callVar[inested-1])
1265 allSubscripts = shumanIsCalledOn.findall(
1266 './/{*}R-LT/{*}array-R/' +
1267 '{*}section-subscript-LT')
1271 arrayDim = len(var[
'as'])
1275 if len(allSubscripts) > 0:
1276 for subLT
in allSubscripts:
1278 lowerBound = sub.findall(
'.//{*}lower-bound')
1279 if len(lowerBound) > 0:
1280 if len(sub.findall(
'.//{*}upper-bound')) > 0:
1283 raise PYFTError(
'ShumanFUNCtoCALL does ' +
1284 'not handle conversion ' +
1285 'to routine of array ' +
1286 'subselection lower:upper' +
1287 ': how to set up the ' +
1288 'shape of intermediate ' +
1298 dimWorkingVar =
'REAL, DIMENSION('
1299 for dims
in var[
'as'][:arrayDim]:
1300 dimWorkingVar += dims[1] +
','
1301 dimWorkingVar = dimWorkingVar[:-1] +
') ::'
1304 localShumansGradients[alltext(el)] += 1
1308 if foundStmtandCalls[stmt][0].tail:
1309 foundStmtandCalls[stmt][0].tail = \
1310 foundStmtandCalls[stmt][0].tail.replace(
'\n',
'') +
'\n'
1312 foundStmtandCalls[stmt][0].tail =
'\n'
1315 (newCallStmt, newComputeStmt,
1316 nbzshugradwk) = FUNCtoROUTINE(scope, elem, el,
1317 localShumansGradients,
1318 elem
in previousComputeStmt,
1319 nbzshugradwk, arrayDim,
1323 elemToLookFor.append(newCallStmt)
1327 if len(newComputeStmt) > 0:
1328 elemToLookFor.append(newComputeStmt)
1329 computeStmtforParenthesis.append(newComputeStmt)
1333 previousComputeStmt.append(newComputeStmt)
1337 elemToLookForNew = []
1338 for i
in elemToLookFor:
1339 nodeNs = i.findall(
'.//{*}n')
1342 if alltext(nnn)
in list(localShumansGradients):
1343 elemToLookForNew.append(i)
1345 elemToLookFor = elemToLookForNew
1348 if nbzshugradwk > maxnbZshugradwk:
1349 maxnbZshugradwk = nbzshugradwk
1352 scope.addArrayParenthesesInNode(foundStmtandCalls[stmt][0])
1356 if tag(foundStmtandCalls[stmt][0]) !=
'call-stmt':
1359 dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes = \
1360 getDimsAndMNHExpandIndexes(arrayDim, dimWorkingVar)
1362 parStmt = scope.getParent(foundStmtandCalls[stmt][0])
1363 indexForCall = list(parStmt).index(foundStmtandCalls[stmt][0])
1364 mnhOpenDir =
"!$mnh_expand_array(" + mnhExpandArrayIndexes +
")"
1365 mnhCloseDir =
"!$mnh_end_expand_array(" + mnhExpandArrayIndexes +
")"
1366 parStmt.insert(indexForCall,
1367 createElem(
'C', text=
"!$acc kernels", tail=
'\n'))
1368 parStmt.insert(indexForCall + 1,
1369 createElem(
'C', text=mnhOpenDir, tail=
'\n'))
1370 parStmt.insert(indexForCall + 3,
1371 createElem(
'C', text=mnhCloseDir, tail=
'\n'))
1372 parStmt.insert(indexForCall + 4,
1373 createElem(
'C', text=
"!$acc end kernels", tail=
'\n'))
1374 parStmt.insert(indexForCall + 5,
1375 createElem(
'C', text=
"!", tail=
'\n'))
1378 for stmt
in computeStmtforParenthesis:
1379 scope.addArrayParenthesesInNode(stmt)