133 Convert STR%VAR into single local variable contained in compute (a-stmt)
134 and in if-then-stmt, else-if-stmt, where-stmt
136 ZA = 1 + CST%XG ==> ZA = 1 + XCST_G
137 ZA = 1 + PARAM_ICE%XRTMIN(3) ==> ZA = 1 + XPARAM_ICE_XRTMIN3
138 ZRSMIN(1:KRR) = ICED%XRTMIN(1:KRR) => ZRSMIN(1:KRR) = ICEDXRTMIN1KRR(1:KRR)
139 IF(TURBN%CSUBG_MF_PDF=='NONE')THEN => IF(CTURBNSUBG_MF_PDF=='NONE')THEN
141 RESTRICTION : works only if the r-component variable is contained in 1 parent structure.
142 Allowed for conversion : CST%XG
143 Not converted : TOTO%CST%XG (for now, recursion must be coded)
144 Not converted : TOTO%ARRAY(:) (shape of the array must be determined from E1)
146 def convertOneType(component, newVarList, scope):
148 objType = scope.getParent(component, 2)
149 objTypeStr = alltext(objType).upper()
150 namedENn = objType.find(
'.//{*}N/{*}n')
151 structure = namedENn.text
152 variable = component.find(
'.//{*}ct').text.upper()
156 arrayRall = objType.findall(
'.//{*}array-R')
157 if len(arrayRall) > 0:
158 arrayR = copy.deepcopy(arrayRall[0])
159 txt = alltext(arrayR).replace(
',',
'')
160 txt = txt.replace(
':',
'')
161 txt = txt.replace(
'(',
'')
162 txt = txt.replace(
')',
'')
163 arrayIndices = arrayIndices + txt
164 elif len(objType.findall(
'.//{*}element-LT')) > 0:
166 for elem
in objType.findall(
'.//{*}element'):
167 arrayIndices = arrayIndices + alltext(elem)
168 newName = variable[0] + structure + variable[1:] + arrayIndices
169 newName = newName.upper()
173 namedENn.text = newName
174 objType.remove(objType.find(
'.//{*}R-LT'))
175 if len(arrayRall) > 0:
176 objType.insert(1, arrayR)
179 if newName
not in newVarList:
180 if len(arrayRall) == 0:
181 newVarList[newName] = (
None, objTypeStr)
183 newVarList[newName] = (arrayR, objTypeStr)
185 scopes = self.getScopes()
186 if scopes[0].path.split(
'/')[-1].split(
':')[1][:4] ==
'MODD':
188 for scope
in [scope
for scope
in scopes
189 if 'sub:' in scope.path
and 'interface' not in scope.path]:
191 for ifStmt
in (scope.findall(
'.//{*}if-then-stmt') +
192 scope.findall(
'.//{*}else-if-stmt') +
193 scope.findall(
'.//{*}where-stmt')):
194 compo = ifStmt.findall(
'.//{*}component-R')
196 for elcompo
in compo:
197 convertOneType(elcompo, newVarList, scope)
199 for aStmt
in scope.findall(
'.//{*}a-stmt'):
202 if len(aStmt[0].findall(
'.//{*}component-R')) == 0:
203 compoE2 = aStmt.findall(
'.//{*}component-R')
210 nbNamedEinE2 = len(aStmt.findall(
'.//{*}E-2')[0].findall(
'.//{*}named-E/' +
212 if nbNamedEinE2 > 1
or nbNamedEinE2 == 1
and \
213 len(aStmt[0].findall(
'.//{*}R-LT')) == 1:
214 for elcompoE2
in compoE2:
215 convertOneType(elcompoE2, newVarList, scope)
218 for el, var
in newVarList.items():
219 if el[0].upper() ==
'X' or el[0].upper() ==
'P' or el[0].upper() ==
'Z':
221 elif el[0].upper() ==
'L' or el[0].upper() ==
'O':
223 elif el[0].upper() ==
'N' or el[0].upper() ==
'I' or el[0].upper() ==
'K':
225 elif el[0].upper() ==
'C':
226 varType =
'CHARACTER(LEN=LEN(' + var[1] +
'))'
228 raise PYFTError(
'Case not implemented for the first letter of the newVarName' +
229 el +
' in convertTypesInCompute')
233 varArray =
', DIMENSION('
234 for i, sub
in enumerate(var[0].findall(
'.//{*}section-subscript')):
235 if len(sub.findall(
'.//{*}upper-bound')) > 0:
236 dimSize = simplifyExpr(
237 alltext(sub.findall(
'.//{*}upper-bound')[0]) +
238 '-' + alltext(sub.findall(
'.//{*}lower-bound')[0]) +
240 elif len(sub.findall(
'.//{*}lover-bound')) > 0:
241 dimSize = simplifyExpr(alltext(sub.findall(
'.//{*}lower-bound')[0]))
243 dimSize =
'SIZE(' + var[1] +
',' + str(i+1) +
')'
244 varArray =
', DIMENSION(' + dimSize +
','
245 varArray = varArray[:-1] +
')'
246 scope.addVar([[scope.path, el, varType + varArray +
' :: ' + el,
None]])
249 stmtAffect = createExpr(el +
"=" + var[1])[0]
250 scope.insertStatement(scope.indent(stmtAffect), first=
True)
320 Add MPPDB_CHEKS on all intent REAL arrays on subroutines.
321 ****** Not applied on modd_ routines. ********
322 Handle optional arguments.
323 Example, for a BL89 routine with 4 arguments, 1 INTENT(IN),
324 2 INTENT(INOUT), 1 INTENT(OUT), it produces :
325 IF (MPPDB_INITIALIZED) THEN
327 CALL MPPDB_CHECK(PZZ, "BL89 beg:PZZ")
328 !Check all INOUT arrays
329 CALL MPPDB_CHECK(PDZZ, "BL89 beg:PDZZ")
330 CALL MPPDB_CHECK(PTHVREF, "BL89 beg:PTHVREF")
333 IF (MPPDB_INITIALIZED) THEN
334 !Check all INOUT arrays
335 CALL MPPDB_CHECK(PDZZ, "BL89 end:PDZZ")
336 CALL MPPDB_CHECK(PTHVREF, "BL89 end:PTHVREF")
337 !Check all OUT arrays
338 CALL MPPDB_CHECK(PLM, "BL89 end:PLM")
340 param printsMode: if True, instead of CALL MPPDB_CHECK, add fortran prints for debugging
342 def addPrints_statement(var, typeofPrints='minmax'):
343 ifBeg, ifEnd =
'',
''
346 if typeofPrints ==
'minmax':
347 strMSG = f
'MINMAX {varName} = \",MINVAL({varName}), MAXVAL({varName})'
348 elif typeofPrints ==
'shape':
349 strMSG = f
'SHAPE {varName} = \",SHAPE({varName})'
351 raise PYFTError(
'typeofPrints is either minmax or shape in addPrints_statement')
353 strMSG = var[
'n'] +
' = \",' + var[
'n']
355 ifBeg = ifBeg +
'IF (PRESENT(' + var[
'n'] +
')) THEN\n '
356 ifEnd = ifEnd +
'\nEND IF'
357 return createExpr(ifBeg +
"print*,\"" + strMSG + ifEnd)[0]
359 def addMPPDB_CHECK_statement(var, subRoutineName, strMSG='beg:
'):
360 ifBeg, ifEnd, addD, addLastDim, addSecondDimType = '',
'',
'',
'',
''
364 if 'D%NIJT' in var[
'as'][0][1]:
366 if len(var[
'as']) == 2:
368 addLastDim =
', ' + var[
'as'][1][1]
369 if len(var[
'as']) >= 2:
372 if 'D%NK' in var[
'as'][1][1]:
373 addSecondDimType =
',' +
'''"VERTICAL"'''
375 addSecondDimType =
',' +
'''"OTHER"'''
376 if 'MERGE' in var[
'as'][-1][1]:
377 keyDimMerge = var[
'as'][-1][1].split(
',')[2][:-1]
378 ifBeg =
'IF (' + keyDimMerge +
') THEN\n'
381 ifBeg = ifBeg +
'IF (PRESENT(' + var[
'n'] +
')) THEN\n IF (SIZE(' + \
382 var[
'n'] +
',1) > 0) THEN\n'
383 ifEnd = ifEnd +
'\nEND IF\nEND IF'
384 argsMPPDB = var[
'n'] +
", " +
"\"" + subRoutineName +
" " + strMSG+var[
'n'] +
"\""
385 return createExpr(ifBeg +
"CALL MPPDB_CHECK(" + addD + argsMPPDB +
386 addLastDim + addSecondDimType +
")" + ifEnd)[0]
387 scopes = self.getScopes()
388 if scopes[0].path.split(
'/')[-1].split(
':')[1][:4] ==
'MODD':
395 if 'sub:' in scope.path
and 'func' not in scope.path
and 'interface' not in scope.path:
396 subRoutineName = scope.path.split(
'/')[-1].split(
':')[1]
399 arraysIn, arraysInOut, arraysOut = [], [], []
401 for var
in scope.varList:
402 if var[
'arg']
and var[
'as']
and 'TYPE' not in var[
't']
and \
403 'REAL' in var[
't']
and var[
'scopePath'] == scope.path:
406 if var[
'i'] ==
'INOUT':
407 arraysInOut.append(var)
408 if var[
'i'] ==
'OUT':
409 arraysOut.append(var)
411 for var
in scope.varList:
412 if not var[
't']
or var[
't']
and 'TYPE' not in var[
't']:
415 if var[
'i'] ==
'INOUT':
416 arraysInOut.append(var)
417 if var[
'i'] ==
'OUT':
418 arraysOut.append(var)
420 if len(arraysIn) + len(arraysInOut) + len(arraysOut) == 0:
425 scope.addModuleVar([(scope.path,
'MODE_MPPDB',
None)])
427 scope.addModuleVar([(scope.path,
'MODD_BLANK_n', [
'LDUMMY1'])])
430 commentIN = createElem(
'C', text=
'!Check all IN arrays', tail=
'\n')
431 commentINOUT = createElem(
'C', text=
'!Check all INOUT arrays', tail=
'\n')
432 commentOUT = createElem(
'C', text=
'!Check all OUT arrays', tail=
'\n')
435 if len(arraysIn) + len(arraysInOut) > 0:
437 ifMPPDBinit = createExpr(
"IF (MPPDB_INITIALIZED) THEN\n END IF")[0]
439 ifMPPDBinit = createExpr(
"IF (LDUMMY1) THEN\n END IF")[0]
440 ifMPPDB = ifMPPDBinit.find(
'.//{*}if-block')
443 if len(arraysIn) > 0:
444 ifMPPDB.insert(1, commentIN)
445 for i, var
in enumerate(arraysIn):
447 ifMPPDB.insert(2 + i, addMPPDB_CHECK_statement(var, subRoutineName,
450 ifMPPDB.insert(2 + i, addPrints_statement(var,
451 typeofPrints=
'minmax'))
452 ifMPPDB.insert(3 + i, addPrints_statement(var,
453 typeofPrints=
'shape'))
456 if len(arraysInOut) > 0:
457 shiftLineNumber = 2
if len(arraysIn) > 0
else 1
459 ifMPPDB.insert(len(arraysIn) + shiftLineNumber, commentINOUT)
461 ifMPPDB.insert(len(arraysIn)*2 + shiftLineNumber-1, commentINOUT)
463 for i, var
in enumerate(arraysInOut):
465 ifMPPDB.insert(len(arraysIn) + shiftLineNumber + 1 + i,
466 addMPPDB_CHECK_statement(var, subRoutineName,
469 ifMPPDB.insert(len(arraysIn) + shiftLineNumber + 1 + i,
470 addPrints_statement(var, typeofPrints=
'minmax'))
473 scope.insertStatement(scope.indent(ifMPPDBinit), first=
True)
476 if len(arraysInOut) + len(arraysOut) > 0:
478 ifMPPDBend = createExpr(
"IF (MPPDB_INITIALIZED) THEN\n END IF")[0]
480 ifMPPDBend = createExpr(
"IF (LDUMMY1) THEN\n END IF")[0]
481 ifMPPDB = ifMPPDBend.find(
'.//{*}if-block')
484 if len(arraysInOut) > 0:
485 ifMPPDB.insert(1, commentINOUT)
486 for i, var
in enumerate(arraysInOut):
488 ifMPPDB.insert(2 + i, addMPPDB_CHECK_statement(var, subRoutineName,
491 ifMPPDB.insert(2 + i, addPrints_statement(var,
492 typeofPrints=
'minmax'))
495 if len(arraysOut) > 0:
496 shiftLineNumber = 2
if len(arraysInOut) > 0
else 1
498 ifMPPDB.insert(len(arraysInOut) + shiftLineNumber, commentOUT)
500 ifMPPDB.insert(len(arraysInOut)*2 + shiftLineNumber-1, commentOUT)
501 for i, var
in enumerate(arraysOut):
503 ifMPPDB.insert(len(arraysInOut) + shiftLineNumber + 1 + i,
504 addMPPDB_CHECK_statement(var, subRoutineName,
507 ifMPPDB.insert(len(arraysInOut) + shiftLineNumber + 1 + i,
508 addPrints_statement(var, typeofPrints=
'minmax'))
511 scope.insertStatement(scope.indent(ifMPPDBend), first=
False)
619 def removeIJDim(self, stopScopes, parserOptions=None, wrapH=False, simplify=False):
621 Transform routines to be called in a loop on columns
622 :param stopScopes: scope paths where we stop to add the D argument (if needed)
623 :param parserOptions, wrapH: see the PYFT class
624 :param simplify: try to simplify code (remove useless dimensions in call)
626 ComputeInSingleColumn :
627 - Remove all Do loops on JI and JJ
628 - Initialize former indexes JI, JJ, JIJ to first array element:
629 JI=D%NIB, JJ=D%NJB, JIJ=D%NIJB
630 - If simplify is True, replace (:,*) on I/J/IJ dimension on argument
631 with explicit (:,*) on CALL statements:
632 e.g. CALL FOO(D, A(:,JK,1), B(:,:))
633 ==> CALL FOO(D, A(JIJ,JK,1), B(:,:)) only if the target argument is not an array
636 indexToCheck = {
'JI': (
'D%NIB',
'D%NIT'),
637 'JJ': (
'D%NJB',
'D%NJT'),
638 'JIJ': (
'D%NIJB',
'D%NIJT')}
640 def slice2index(namedE, scope):
642 Transform a slice on the horizontal dimension into an index
643 Eg.: X(1:D%NIJT, 1:D%NKT) => X(JIJ, 1:D%NKT) Be careful, this array is not contiguous.
644 X(1:D%NIJT, JK) => X(JIJ, JK)
645 :param namedE: array to transform
646 :param scope: scope where the array is
649 for isub, sub
in enumerate(namedE.findall(
'./{*}R-LT/{*}array-R/' +
650 '{*}section-subscript-LT/' +
651 '{*}section-subscript')):
652 if ':' in alltext(sub):
653 loopIndex, _, _ = scope.findIndexArrayBounds(namedE, isub, _loopVarPHYEX)
654 if loopIndex
in indexToCheck:
657 lowerBound = createElem(
'lower-bound')
658 sub.insert(0, lowerBound)
660 lowerBound = sub.find(
'./{*}lower-bound')
662 for item
in lowerBound:
663 lowerBound.remove(item)
664 upperBound = sub.find(
'./{*}upper-bound')
665 if upperBound
is not None:
666 sub.remove(upperBound)
667 lowerBound.append(createExprPart(loopIndex))
668 if loopIndex
not in indexRemoved:
669 indexRemoved.append(loopIndex)
672 if ':' not in alltext(namedE.find(
'./{*}R-LT/{*}array-R/{*}section-subscript-LT')):
673 namedE.find(
'./{*}R-LT/{*}array-R').tag = f
'{{{NAMESPACE}}}parens-R'
674 namedE.find(
'./{*}R-LT/{*}parens-R/' +
675 '{*}section-subscript-LT').tag = f
'{{{NAMESPACE}}}element-LT'
676 for ss
in namedE.findall(
'./{*}R-LT/{*}parens-R/' +
677 '{*}element-LT/{*}section-subscript'):
678 ss.tag = f
'{{{NAMESPACE}}}element'
679 lowerBound = ss.find(
'./{*}lower-bound')
680 for item
in lowerBound:
682 ss.remove(lowerBound)
685 self.addArrayParentheses()
688 self.attachArraySpecToEntity()
689 hUupperBounds = [v[1]
for v
in indexToCheck.values()]
693 for scope
in [scope
for scope
in self.getScopes()[::-1]
694 if 'func:' not in scope.path
and
695 (scope.path
in stopScopes
or
696 self.tree.isUnderStopScopes(scope.path, stopScopes,
697 includeInterfaces=
True))]:
703 for doNode
in scope.findall(
'.//{*}do-construct')[::-1]:
704 for loopI
in doNode.findall(
'./{*}do-stmt/{*}do-V/{*}named-E/{*}N'):
705 loopIname = n2name(loopI).upper()
706 if loopIname
in indexToCheck:
709 par = scope.getParent(doNode)
710 index = list(par).index(doNode)
711 for item
in doNode[1:-1][::-1]:
712 par.insert(index, item)
714 if loopIname
not in indexRemoved:
715 indexRemoved.append(loopIname)
720 for intr
in scope.findall(
'.//{*}R-LT/{*}parens-R/../..'):
721 intrName = n2name(intr.find(
'./{*}N')).upper()
722 if intrName
in (
'PACK',
'UNPACK',
'COUNT',
'MAXVAL',
'MINVAL',
'ALL',
'ANY',
'SUM'):
730 while par
is not None and not isStmt(par):
731 par = scope.getParent(par)
732 if tag(par)
in (
'a-stmt',
'op-E'):
737 for namedE
in parToUse.findall(
'.//{*}R-LT/{*}array-R/../..'):
738 slice2index(namedE, scope)
741 if intr.find(
'.//{*}R-LT/{*}array-R')
is None:
742 if intrName
in (
'MAXVAL',
'MINVAL',
'SUM',
'ALL',
'ANY'):
744 parens = intr.find(
'./{*}R-LT/{*}parens-R')
745 parens.tag = f
'{{{NAMESPACE}}}parens-E'
746 intrPar = scope.getParent(intr)
747 intrPar.insert(list(intrPar).index(intr), parens)
749 elif intrName ==
'COUNT':
751 nodeN = intr.find(
'./{*}N')
752 for item
in nodeN[1:]:
754 nodeN.find(
'./{*}n').text =
'MERGE'
755 elementLT = intr.find(
'./{*}R-LT/{*}parens-R/{*}element-LT')
757 element = createElem(
'element', tail=
', ')
758 element.append(createExprPart(val))
759 elementLT.insert(0, element)
772 assert scope.find(
'.//{*}include')
is None and \
773 scope.find(
'.//{*}include-stmt')
is None, \
774 "inlining must be performed before removing horizontal dimensions"
776 if scope.path
in stopScopes:
778 preserveShape = [v[
'n']
for v
in scope.varList
if v[
'arg']]
783 if 'sub:' in scope.path:
787 for namedE
in scope.findall(
'.//{*}named-E/{*}R-LT/{*}parens-R/../..'):
788 if n2name(namedE.find(
'./{*}N')).upper()
not in preserveShape:
789 var = scope.varList.findVar(n2name(namedE.find(
'./{*}N')).upper())
790 if var
is not None and var[
'as']
is not None and len(var[
'as']) > 0:
791 subs = namedE.findall(
'./{*}R-LT/{*}parens-R/' +
792 '{*}element-LT/{*}element')
793 if (len(subs) == 1
and var[
'as'][0][1]
in hUupperBounds)
or \
794 (len(subs) == 2
and (var[
'as'][0][1]
in hUupperBounds
and
795 var[
'as'][1][1]
in hUupperBounds)):
796 namedE.remove(namedE.find(
'./{*}R-LT'))
800 for call
in scope.findall(
'.//{*}call-stmt'):
801 for namedE
in call.findall(
'./{*}arg-spec//{*}named-E'):
802 subs = namedE.findall(
'.//{*}section-subscript')
803 var = scope.varList.findVar(n2name(namedE.find(
'./{*}N')).upper())
804 if len(subs) > 0
and (var
is None or var[
'as']
is None or
805 len(var[
'as']) < len(subs)):
813 elif (len(subs) >= 2
and
814 ':' in alltext(subs[0])
and var[
'as'][0][1]
in hUupperBounds
and
815 ':' in alltext(subs[1])
and var[
'as'][1][1]
in hUupperBounds):
817 remove = len(subs) == 2
818 index = (len(subs) > 2
and
819 len([sub
for sub
in subs
if ':' in alltext(sub)]) == 2)
820 elif (len(subs) >= 1
and
821 ':' in alltext(subs[0])
and var[
'as'][0][1]
in hUupperBounds):
823 remove = len(subs) == 1
824 index = (len(subs) > 1
and
825 len([sub
for sub
in subs
if ':' in alltext(sub)]) == 1)
830 if n2name(namedE.find(
'./{*}N')).upper()
in preserveShape:
831 slice2index(namedE, scope)
833 nodeRLT = namedE.find(
'.//{*}R-LT')
834 scope.getParent(nodeRLT).remove(nodeRLT)
836 slice2index(namedE, scope)
841 for decl
in scope.findall(
'.//{*}T-decl-stmt/{*}EN-decl-LT/{*}EN-decl'):
842 name = n2name(decl.find(
'./{*}EN-N/{*}N')).upper()
843 if name
not in preserveShape:
844 varsShape = decl.findall(
'.//{*}shape-spec-LT')
845 for varShape
in varsShape:
846 subs = varShape.findall(
'.//{*}shape-spec')
847 if (len(subs) == 1
and alltext(subs[0])
in hUupperBounds)
or \
848 (len(subs) == 2
and (alltext(subs[0])
in hUupperBounds
and
849 alltext(subs[1])
in hUupperBounds)):
851 itemToRemove = scope.getParent(varShape)
852 scope.getParent(itemToRemove).remove(itemToRemove)
857 for loopIndex
in indexRemoved:
860 scope.insertStatement(
861 createExpr(loopIndex +
" = " + indexToCheck[loopIndex][0])[0],
True)
862 if len(indexRemoved) > 0:
863 scope.addArgInTree(
'D',
'TYPE(DIMPHYEX_t) :: D',
864 0, stopScopes, moduleVarList=[(
'MODD_DIMPHYEX', [
'DIMPHYEX_t'])],
865 parserOptions=parserOptions, wrapH=wrapH)
867 scope.addVar([[scope.path, loopIndex,
'INTEGER :: ' + loopIndex,
None]
868 for loopIndex
in indexRemoved
869 if scope.varList.findVar(loopIndex, exactScope=
True)
is None])
1065 Convert all calling of functions and gradient present in shumansGradients
1066 table into the use of subroutines
1067 and use mnh_expand_directives to handle intermediate computations
1069 def getDimsAndMNHExpandIndexes(zshugradwkDim, dimWorkingVar=''):
1071 if zshugradwkDim == 1:
1072 dimSuffRoutine =
'2D'
1074 mnhExpandArrayIndexes =
'JIJ=IIJB:IIJE'
1075 localVariables = [
'JIJ']
1076 elif zshugradwkDim == 2:
1078 if 'D%NKT' in dimWorkingVar:
1079 mnhExpandArrayIndexes =
'JIJ=IIJB:IIJE,JK=1:IKT'
1080 localVariables = [
'JIJ',
'JK']
1081 elif 'D%NIT' in dimWorkingVar
and 'D%NJT' in dimWorkingVar:
1083 mnhExpandArrayIndexes =
'JI=1:IIT,JJ=1:IJT'
1084 localVariables = [
'JI',
'JJ']
1085 dimSuffRoutine =
'2D'
1091 mnhExpandArrayIndexes =
'JIJ=IIJB:IIJE,JK=1:IKT'
1092 localVariables = [
'JIJ',
'JK']
1093 elif zshugradwkDim == 3:
1095 mnhExpandArrayIndexes =
'JI=1:IIT,JJ=1:IJT,JK=1:IKT'
1096 localVariables = [
'JI',
'JJ',
'JK']
1098 raise PYFTError(
'Shuman func to routine conversion not implemented ' +
1099 'for 4D+ dimensions variables')
1100 return dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes, localVariables
1102 def FUNCtoROUTINE(scope, stmt, itemFuncN, localShumansCount, inComputeStmt,
1103 nbzshugradwk, zshugradwkDim, dimWorkingVar):
1105 :param scope: node on which the calling function is present before transformation
1106 :param stmt: statement node (a-stmt or call-stmt) that contains the function(s) to be
1108 :param itemFuncN: <n>FUNCTIONNAME</n> node
1109 :param localShumansCount: instance of the shumansGradients dictionnary
1110 for the given scope (which contains the number of times a
1111 function has been called within a transformation)
1112 :param dimWorkingVar: string of the declaration of a potential working variable
1113 depending on the array on wich the shuman is applied
1114 (e.g. MZM(PRHODJ(:,IKB));
1115 dimWorkingVar = 'REAL, DIMENSION(D%NIJT) :: ' )
1117 :return callStmt: the new CALL to the routines statement
1118 :return computeStmt: the a-stmt computation statement if there was an operation
1119 in the calling function in stmt
1120 :return localVariables: list of local variables needed for the mnh_expand directive
1124 parStmt = scope.getParent(stmt)
1125 parItemFuncN = scope.getParent(itemFuncN)
1127 grandparItemFuncN = scope.getParent(itemFuncN, level=2)
1128 funcName = alltext(itemFuncN)
1131 indexForCall = list(parStmt).index(stmt)
1136 siblsItemFuncN = scope.getSiblings(parItemFuncN, after=
True, before=
False)
1137 workingItem = siblsItemFuncN[0][0][0]
1140 if len(siblsItemFuncN[0][0]) > 1:
1142 workingItem = scope.updateContinuation(siblsItemFuncN[0][0], removeALL=
True,
1143 align=
False, addBegin=
False)[0]
1147 opE = workingItem.findall(
'.//{*}op-E')
1148 scope.removeArrayParenthesesInNode(workingItem)
1149 computeStmt, remaningArgsofFunc = [],
''
1150 dimSuffVar = str(zshugradwkDim) +
'D'
1151 dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes, _ = \
1152 getDimsAndMNHExpandIndexes(zshugradwkDim, dimWorkingVar)
1155 computingVarName =
'ZSHUGRADWK'+str(nbzshugradwk)+
'_'+str(zshugradwkDim)+
'D'
1157 if not scope.varList.findVar(computingVarName):
1158 scope.addVar([[scope.path, computingVarName,
1159 dimWorkingVar + computingVarName,
None]])
1163 computeVar = scope.varList.findVar(computingVarName)
1164 dimWorkingVar =
'REAL, DIMENSION('
1165 for dims
in computeVar[
'as'][:arrayDim]:
1166 dimWorkingVar += dims[1] +
','
1167 dimWorkingVar = dimWorkingVar[:-1] +
') ::'
1169 dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes, localVariables = \
1170 getDimsAndMNHExpandIndexes(zshugradwkDim, dimWorkingVar)
1173 mnhOpenDir =
"!$mnh_expand_array(" + mnhExpandArrayIndexes +
")"
1174 mnhCloseDir =
"!$mnh_end_expand_array(" + mnhExpandArrayIndexes +
")"
1177 workingComputeItem = workingItem[0]
1179 if len(workingItem) == 2:
1180 remaningArgsofFunc =
',' + alltext(workingItem[1])
1181 elif len(workingItem) > 2:
1182 raise PYFTError(
'ShumanFUNCtoCALL: expected maximum 1 argument in shuman ' +
1183 'function to transform')
1184 computeStmt = createExpr(computingVarName +
" = " + alltext(workingComputeItem))[0]
1185 workingItem = computeStmt.find(
'.//{*}E-1')
1187 parStmt.insert(indexForCall, createElem(
'C', text=
'!$acc kernels', tail=
'\n'))
1188 parStmt.insert(indexForCall + 1, createElem(
'C', text=mnhOpenDir, tail=
'\n'))
1189 parStmt.insert(indexForCall + 2, computeStmt)
1190 parStmt.insert(indexForCall + 3, createElem(
'C', text=mnhCloseDir, tail=
'\n'))
1191 parStmt.insert(indexForCall + 4, createElem(
'C',
1192 text=
'!$acc end kernels', tail=
'\n'))
1193 parStmt.insert(indexForCall + 5, createElem(
'C',
1194 text=
'!', tail=
'\n'))
1198 if zshugradwkDim == 1:
1199 dimSuffRoutine =
'2D'
1200 workingVar =
'Z' + funcName + dimSuffVar +
'_WORK' + str(localShumansCount[funcName])
1201 if funcName
in (
'GY_U_UV',
'GX_V_UV'):
1202 gpuGradientImplementation =
'_DEVICE('
1203 newFuncName = funcName + dimSuffRoutine +
'_DEVICE'
1205 gpuGradientImplementation =
'_PHY(D, '
1206 newFuncName = funcName + dimSuffRoutine +
'_PHY'
1207 callStmt = createExpr(
"CALL " + funcName + dimSuffRoutine + gpuGradientImplementation
1208 + alltext(workingItem) + remaningArgsofFunc +
1209 ", " + workingVar +
")")[0]
1210 parStmt.insert(indexForCall, callStmt)
1213 parOfgrandparItemFuncN = scope.getParent(grandparItemFuncN)
1214 indexWorkingVar = list(parOfgrandparItemFuncN).index(grandparItemFuncN)
1215 savedTail = grandparItemFuncN.tail
1216 parOfgrandparItemFuncN.remove(grandparItemFuncN)
1219 xmlWorkingvar = createExprPart(workingVar)
1220 xmlWorkingvar.tail = savedTail
1221 parOfgrandparItemFuncN.insert(indexWorkingVar, xmlWorkingvar)
1224 if not scope.varList.findVar(workingVar):
1225 scope.addVar([[scope.path, workingVar, dimWorkingVar + workingVar,
None]])
1227 return callStmt, computeStmt, nbzshugradwk, newFuncName, localVariables
1229 shumansGradients = {
'MZM': 0,
'MXM': 0,
'MYM': 0,
'MZF': 0,
'MXF': 0,
'MYF': 0,
1230 'DZM': 0,
'DXM': 0,
'DYM': 0,
'DZF': 0,
'DXF': 0,
'DYF': 0,
1231 'GZ_M_W': 0,
'GZ_W_M': 0,
'GZ_U_UW': 0,
'GZ_V_VW': 0,
1232 'GX_M_U': 0,
'GX_U_M': 0,
'GX_W_UW': 0,
'GX_M_M': 0,
1233 'GY_V_M': 0,
'GY_M_V': 0,
'GY_W_VW': 0,
'GY_M_M': 0,
1234 'GX_V_UV': 0,
'GY_U_UV': 0}
1235 scopes = self.getScopes()
1236 if len(scopes) == 0
or scopes[0].path.split(
'/')[-1].split(
':')[1][:4] ==
'MODD':
1238 for scope
in scopes:
1239 if 'sub:' in scope.path
and 'func' not in scope.path \
1240 and 'interface' not in scope.path:
1243 localVariablesToAdd = set()
1244 foundStmtandCalls, computeStmtforParenthesis = {}, []
1245 aStmt = scope.findall(
'.//{*}a-stmt')
1246 callStmts = scope.findall(
'.//{*}call-stmt')
1247 aStmtandCallStmts = aStmt + callStmts
1248 for stmt
in aStmtandCallStmts:
1249 elemN = stmt.findall(
'.//{*}n')
1251 if alltext(el)
in list(shumansGradients):
1254 parStmt = scope.getParent(stmt)
1255 if tag(parStmt) ==
'action-stmt':
1256 scope.changeIfStatementsInIfConstructs(
1257 singleItem=scope.getParent(parStmt))
1259 if str(stmt)
in foundStmtandCalls:
1260 foundStmtandCalls[str(stmt)][1] += 1
1262 foundStmtandCalls[str(stmt)] = [stmt, 1]
1265 subToInclude = set()
1266 for stmt
in foundStmtandCalls:
1267 localShumansGradients = copy.deepcopy(shumansGradients)
1268 elemToLookFor = [foundStmtandCalls[stmt][0]]
1269 previousComputeStmt = []
1272 while len(elemToLookFor) > 0:
1274 for elem
in elemToLookFor:
1275 elemN = elem.findall(
'.//{*}n')
1277 if alltext(el)
in list(localShumansGradients.keys()):
1282 nodeE1var = foundStmtandCalls[stmt][0].findall(
1283 './/{*}E-1/{*}named-E/{*}N')
1284 if len(nodeE1var) > 0:
1285 var = scope.varList.findVar(alltext(nodeE1var[0]))
1286 allSubscripts = foundStmtandCalls[stmt][0].findall(
1287 './/{*}E-1//{*}named-E/{*}R-LT/' +
1288 '{*}array-R/{*}section-subscript-LT')
1292 elPar = scope.getParent(el, level=2)
1293 callVar = elPar.findall(
'.//{*}named-E/{*}N')
1294 if alltext(el)[0] ==
'G':
1299 var = scope.varList.findVar(alltext(callVar[-1]))
1300 shumanIsCalledOn = scope.getParent(callVar[-1])
1303 var, inested =
None, 0
1305 while not var
or len(var[
'as']) == 0:
1309 var = scope.varList.findVar(
1310 alltext(callVar[inested]))
1312 shumanIsCalledOn = scope.getParent(callVar[inested-1])
1313 allSubscripts = shumanIsCalledOn.findall(
1314 './/{*}R-LT/{*}array-R/' +
1315 '{*}section-subscript-LT')
1319 arrayDim = len(var[
'as'])
1323 if len(allSubscripts) > 0:
1324 for subLT
in allSubscripts:
1326 lowerBound = sub.findall(
'.//{*}lower-bound')
1327 if len(lowerBound) > 0:
1328 if len(sub.findall(
'.//{*}upper-bound')) > 0:
1331 raise PYFTError(
'ShumanFUNCtoCALL does ' +
1332 'not handle conversion ' +
1333 'to routine of array ' +
1334 'subselection lower:upper' +
1335 ': how to set up the ' +
1336 'shape of intermediate ' +
1346 dimWorkingVar =
'REAL, DIMENSION('
1347 for dims
in var[
'as'][:arrayDim]:
1348 dimWorkingVar += dims[1] +
','
1349 dimWorkingVar = dimWorkingVar[:-1] +
') ::'
1352 localShumansGradients[alltext(el)] += 1
1356 if foundStmtandCalls[stmt][0].tail:
1357 foundStmtandCalls[stmt][0].tail = \
1358 foundStmtandCalls[stmt][0].tail.replace(
'\n',
'') +
'\n'
1360 foundStmtandCalls[stmt][0].tail =
'\n'
1363 result = FUNCtoROUTINE(scope, elem, el,
1364 localShumansGradients,
1365 elem
in previousComputeStmt,
1366 nbzshugradwk, arrayDim,
1368 (newCallStmt, newComputeStmt,
1369 nbzshugradwk, newFuncName, lv) = result
1370 localVariablesToAdd.update(lv)
1371 subToInclude.add(newFuncName)
1374 elemToLookFor.append(newCallStmt)
1378 if len(newComputeStmt) > 0:
1379 elemToLookFor.append(newComputeStmt)
1380 computeStmtforParenthesis.append(newComputeStmt)
1384 previousComputeStmt.append(newComputeStmt)
1388 elemToLookForNew = []
1389 for i
in elemToLookFor:
1390 nodeNs = i.findall(
'.//{*}n')
1393 if alltext(nnn)
in list(localShumansGradients):
1394 elemToLookForNew.append(i)
1396 elemToLookFor = elemToLookForNew
1399 if nbzshugradwk > maxnbZshugradwk:
1400 maxnbZshugradwk = nbzshugradwk
1403 scope.addArrayParenthesesInNode(foundStmtandCalls[stmt][0])
1407 if tag(foundStmtandCalls[stmt][0]) !=
'call-stmt':
1410 dimSuffRoutine, dimSuffVar, mnhExpandArrayIndexes, lv = \
1411 getDimsAndMNHExpandIndexes(arrayDim, dimWorkingVar)
1412 localVariablesToAdd.update(lv)
1414 parStmt = scope.getParent(foundStmtandCalls[stmt][0])
1415 indexForCall = list(parStmt).index(foundStmtandCalls[stmt][0])
1416 mnhOpenDir =
"!$mnh_expand_array(" + mnhExpandArrayIndexes +
")"
1417 mnhCloseDir =
"!$mnh_end_expand_array(" + mnhExpandArrayIndexes +
")"
1418 parStmt.insert(indexForCall,
1419 createElem(
'C', text=
"!$acc kernels", tail=
'\n'))
1420 parStmt.insert(indexForCall + 1,
1421 createElem(
'C', text=mnhOpenDir, tail=
'\n'))
1422 parStmt.insert(indexForCall + 3,
1423 createElem(
'C', text=mnhCloseDir, tail=
'\n'))
1424 parStmt.insert(indexForCall + 4,
1425 createElem(
'C', text=
"!$acc end kernels", tail=
'\n'))
1426 parStmt.insert(indexForCall + 5,
1427 createElem(
'C', text=
"!", tail=
'\n'))
1430 for stmt
in computeStmtforParenthesis:
1431 scope.addArrayParenthesesInNode(stmt)
1435 for sub
in sorted(subToInclude):
1436 if re.match(
r'[MD][XYZ][MF](2D)?_PHY', sub):
1437 moduleVars.append((scope.path,
'MODE_SHUMAN_PHY', sub))
1439 for kind
in (
'M',
'U',
'V',
'W'):
1440 if re.match(
r'G[XYZ]_' + kind +
r'_[MUVW]{1,2}_PHY', sub):
1441 moduleVars.append((scope.path, f
'MODE_GRADIENT_{kind}_PHY', sub))
1442 scope.addModuleVar(moduleVars)
1445 for varName
in localVariablesToAdd:
1446 if not scope.varList.findVar(varName):
1447 var = {
'as': [],
'asx': [],
1448 'n': varName,
'i':
None,
't':
'INTEGER',
'arg':
False,
1449 'use':
False,
'opt':
False,
'allocatable':
False,
1450 'parameter':
False,
'init':
None,
'scopePath': scope.path}
1451 scope.addVar([[scope.path, var[
'n'], scope.varSpec2stmt(var),
None]])