Changeset 23783


Ignore:
Timestamp:
03/08/19 14:58:19 (6 years ago)
Author:
kruegern
Message:

BUG: translated new checkfield size check to python, fixed constants size check condition, fixed transient.py tab-alignment problem

Location:
issm/trunk-jpl/src/m
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/m/classes/constants.py

    r22267 r23783  
    4949        def checkconsistency(self,md,solution,analyses):    # {{{
    5050
    51                 md = checkfield(md,'fieldname','constants.g','>=',0,'size',[1,1])
    52                 md = checkfield(md,'fieldname','constants.omega','>=',0,'size',[1,1])
    53                 md = checkfield(md,'fieldname','constants.yts','>',0,'size',[1,1])
    54                 md = checkfield(md,'fieldname','constants.referencetemperature','size',[1,1])
     51                md = checkfield(md,'fieldname','constants.g','>=',0,'size',[1])
     52                md = checkfield(md,'fieldname','constants.omega','>=',0,'size',[1])
     53                md = checkfield(md,'fieldname','constants.yts','>',0,'size',[1])
     54                md = checkfield(md,'fieldname','constants.referencetemperature','size',[1])
    5555
    5656                return md
  • issm/trunk-jpl/src/m/classes/transient.py

    r23770 r23783  
    44
    55class transient(object):
    6         """
    7         TRANSIENT class definition
     6    """
     7    TRANSIENT class definition
    88
    9            Usage:
    10               transient=transient();
    11         """
     9       Usage:
     10          transient=transient();
     11    """
    1212
    13         def __init__(self): # {{{
    14                 self.issmb             = False
    15                 self.ismasstransport   = False
    16                 self.isstressbalance   = False
    17                 self.isthermal         = False
    18                 self.isgroundingline   = False
    19                 self.isgia             = False
    20                 self.isesa             = False
    21                 self.isdamageevolution = False
    22                 self.ismovingfront     = False
    23                 self.ishydrology       = False
    24                 self.isslr             = False
    25                 self.iscoupler         = False
    26                 self.amr_frequency     = 0
    27                 self.isoceancoupling   = False
    28                 self.requested_outputs = []
     13    def __init__(self): # {{{
     14        self.issmb              = False
     15        self.ismasstransport   = False
     16        self.isstressbalance   = False
     17        self.isthermal         = False
     18        self.isgroundingline   = False
     19        self.isgia             = False
     20        self.isesa             = False
     21        self.isdamageevolution = False
     22        self.ismovingfront     = False
     23        self.ishydrology       = False
     24        self.isslr             = False
     25        self.iscoupler         = False
     26        self.amr_frequency     = 0
     27        self.isoceancoupling   = False
     28        self.requested_outputs = []
    2929
    30                 #set defaults
    31                 self.setdefaultparameters()
     30        #set defaults
     31        self.setdefaultparameters()
    3232
    33                 #}}}
    34         def __repr__(self): # {{{
    35                 string='   transient solution parameters:'
    36                 string="%s\n%s"%(string,fielddisplay(self,'issmb','indicates if a surface mass balance solution is used in the transient'))
    37                 string="%s\n%s"%(string,fielddisplay(self,'ismasstransport','indicates if a masstransport solution is used in the transient'))
    38                 string="%s\n%s"%(string,fielddisplay(self,'isstressbalance','indicates if a stressbalance solution is used in the transient'))
    39                 string="%s\n%s"%(string,fielddisplay(self,'isthermal','indicates if a thermal solution is used in the transient'))
    40                 string="%s\n%s"%(string,fielddisplay(self,'isgroundingline','indicates if a groundingline migration is used in the transient'))
    41                 string="%s\n%s"%(string,fielddisplay(self,'isgia','indicates if a postglacial rebound is used in the transient'))
    42                 string="%s\n%s"%(string,fielddisplay(self,'isesa','indicates whether an elastic adjustment model is used in the transient'))
    43                 string="%s\n%s"%(string,fielddisplay(self,'isdamageevolution','indicates whether damage evolution is used in the transient'))
    44                 string="%s\n%s"%(string,fielddisplay(self,'ismovingfront','indicates whether a moving front capability is used in the transient'))
    45                 string="%s\n%s"%(string,fielddisplay(self,'ishydrology','indicates whether an hydrology model is used'))
    46                 string="%s\n%s"%(string,fielddisplay(self,'isslr','indicates if a sea level rise solution is used in the transient'))
    47                 string="%s\n%s"%(string,fielddisplay(self,'isoceancoupling','indicates whether coupling with an ocean model is used in the transient'))
    48                 string="%s\n%s"%(string,fielddisplay(self,'iscoupler','indicates whether different models are being run with need for coupling'))
    49                 string="%s\n%s"%(string,fielddisplay(self,'amr_frequency','frequency at which mesh is refined in simulations with multiple time_steps'))
    50                 string="%s\n%s"%(string,fielddisplay(self,'requested_outputs','list of additional outputs requested'))
    51                 return string
    52                 #}}}
    53         def defaultoutputs(self,md): # {{{
     33        #}}}
     34    def __repr__(self): # {{{
     35        string='   transient solution parameters:'
     36        string="%s\n%s"%(string,fielddisplay(self,'issmb','indicates if a surface mass balance solution is used in the transient'))
     37        string="%s\n%s"%(string,fielddisplay(self,'ismasstransport','indicates if a masstransport solution is used in the transient'))
     38        string="%s\n%s"%(string,fielddisplay(self,'isstressbalance','indicates if a stressbalance solution is used in the transient'))
     39        string="%s\n%s"%(string,fielddisplay(self,'isthermal','indicates if a thermal solution is used in the transient'))
     40        string="%s\n%s"%(string,fielddisplay(self,'isgroundingline','indicates if a groundingline migration is used in the transient'))
     41        string="%s\n%s"%(string,fielddisplay(self,'isgia','indicates if a postglacial rebound is used in the transient'))
     42        string="%s\n%s"%(string,fielddisplay(self,'isesa','indicates whether an elastic adjustment model is used in the transient'))
     43        string="%s\n%s"%(string,fielddisplay(self,'isdamageevolution','indicates whether damage evolution is used in the transient'))
     44        string="%s\n%s"%(string,fielddisplay(self,'ismovingfront','indicates whether a moving front capability is used in the transient'))
     45        string="%s\n%s"%(string,fielddisplay(self,'ishydrology','indicates whether an hydrology model is used'))
     46        string="%s\n%s"%(string,fielddisplay(self,'isslr','indicates if a sea level rise solution is used in the transient'))
     47        string="%s\n%s"%(string,fielddisplay(self,'isoceancoupling','indicates whether coupling with an ocean model is used in the transient'))
     48        string="%s\n%s"%(string,fielddisplay(self,'iscoupler','indicates whether different models are being run with need for coupling'))
     49        string="%s\n%s"%(string,fielddisplay(self,'amr_frequency','frequency at which mesh is refined in simulations with multiple time_steps'))
     50        string="%s\n%s"%(string,fielddisplay(self,'requested_outputs','list of additional outputs requested'))
     51        return string
     52        #}}}
     53    def defaultoutputs(self,md): # {{{
    5454
    55                 if self.issmb:
    56                         return ['SmbMassBalance']
    57                 else:
    58                         return []
     55        if self.issmb:
     56            return ['SmbMassBalance']
     57        else:
     58            return []
    5959
    60         #}}}
    61         def setallnullparameters(self): # {{{
    62                
    63                 #Nothing done
    64                 self.issmb   = False
    65                 self.ismasstransport   = False
    66                 self.isstressbalance   = False
    67                 self.isthermal         = False
    68                 self.isgroundingline   = False
    69                 self.isgia             = False
    70                 self.isesa             = False
    71                 self.isdamageevolution = False
    72                 self.ismovingfront     = False
    73                 self.ishydrology       = False
    74                 self.isoceancoupling   = False
    75                 self.isslr             = False
    76                 self.iscoupler         = False
    77                 self.amr_frequency        = 0
     60    #}}}
     61    def setallnullparameters(self): # {{{
     62       
     63        #Nothing done
     64        self.issmb   = False
     65        self.ismasstransport   = False
     66        self.isstressbalance   = False
     67        self.isthermal         = False
     68        self.isgroundingline   = False
     69        self.isgia             = False
     70        self.isesa             = False
     71        self.isdamageevolution = False
     72        self.ismovingfront     = False
     73        self.ishydrology       = False
     74        self.isoceancoupling   = False
     75        self.isslr             = False
     76        self.iscoupler         = False
     77        self.amr_frequency      = 0
    7878
    79                 #default output
    80                 self.requested_outputs=[]
    81                 return self
    82         #}}}
    83         def deactivateall(self):#{{{
    84                 self.issmb             = False
    85                 self.ismasstransport   = False
    86                 self.isstressbalance   = False
    87                 self.isthermal         = False
    88                 self.isgroundingline   = False
    89                 self.isgia             = False
    90                 self.isesa             = False
    91                 self.isdamageevolution = False
    92                 self.ismovingfront     = False
    93                 self.ishydrology       = False
    94                 self.isslr             = False
    95                 self.isoceancoupling   = False
    96                 self.iscoupler         = False
    97                 self.amr_frequency     = 0
     79        #default output
     80        self.requested_outputs=[]
     81        return self
     82    #}}}
     83    def deactivateall(self):#{{{
     84        self.issmb             = False
     85        self.ismasstransport   = False
     86        self.isstressbalance   = False
     87        self.isthermal         = False
     88        self.isgroundingline   = False
     89        self.isgia             = False
     90        self.isesa             = False
     91        self.isdamageevolution = False
     92        self.ismovingfront     = False
     93        self.ishydrology       = False
     94        self.isslr             = False
     95        self.isoceancoupling   = False
     96        self.iscoupler         = False
     97        self.amr_frequency     = 0
    9898
    99                 #default output
    100                 self.requested_outputs=[]
    101                 return self
    102         #}}}
    103         def setdefaultparameters(self): # {{{
    104                
    105                 #full analysis: Stressbalance, Masstransport and Thermal but no groundingline migration for now
    106                 self.issmb             = True
    107                 self.ismasstransport   = True
    108                 self.isstressbalance   = True
    109                 self.isthermal         = True
    110                 self.isgroundingline   = False
    111                 self.isgia             = False
    112                 self.isesa             = False
    113                 self.isdamageevolution = False
    114                 self.ismovingfront     = False
    115                 self.ishydrology       = False
    116                 self.isslr             = False
    117                 self.isoceancoupling   = False
    118                 self.iscoupler         = False
    119                 self.amr_frequency     = 0
     99        #default output
     100        self.requested_outputs=[]
     101        return self
     102    #}}}
     103    def setdefaultparameters(self): # {{{
     104       
     105        #full analysis: Stressbalance, Masstransport and Thermal but no groundingline migration for now
     106        self.issmb             = True
     107        self.ismasstransport   = True
     108        self.isstressbalance   = True
     109        self.isthermal         = True
     110        self.isgroundingline   = False
     111        self.isgia             = False
     112        self.isesa             = False
     113        self.isdamageevolution = False
     114        self.ismovingfront     = False
     115        self.ishydrology       = False
     116        self.isslr             = False
     117        self.isoceancoupling   = False
     118        self.iscoupler         = False
     119        self.amr_frequency     = 0
    120120
    121                 #default output
    122                 self.requested_outputs=['default']
    123                 return self
    124         #}}}
    125         def checkconsistency(self,md,solution,analyses):    # {{{
     121        #default output
     122        self.requested_outputs=['default']
     123        return self
     124    #}}}
     125    def checkconsistency(self,md,solution,analyses):    # {{{
    126126
    127                 #Early return
    128                 if not solution=='TransientSolution':
    129                         return md
     127        #Early return
     128        if not solution=='TransientSolution':
     129            return md
    130130
    131                 md = checkfield(md,'fieldname','transient.issmb','numel',[1],'values',[0,1])
    132                 md = checkfield(md,'fieldname','transient.ismasstransport','numel',[1],'values',[0,1])
    133                 md = checkfield(md,'fieldname','transient.isstressbalance','numel',[1],'values',[0,1])
    134                 md = checkfield(md,'fieldname','transient.isthermal','numel',[1],'values',[0,1])
    135                 md = checkfield(md,'fieldname','transient.isgroundingline','numel',[1],'values',[0,1])
    136                 md = checkfield(md,'fieldname','transient.isgia','numel',[1],'values',[0,1])
    137                 md = checkfield(md,'fieldname','transient.isesa','numel',[1],'values',[0,1])
    138                 md = checkfield(md,'fieldname','transient.isdamageevolution','numel',[1],'values',[0,1])
    139                 md = checkfield(md,'fieldname','transient.ishydrology','numel',[1],'values',[0,1])
    140                 md = checkfield(md,'fieldname','transient.ismovingfront','numel',[1],'values',[0,1]);
    141                 md = checkfield(md,'fieldname','transient.isslr','numel',[1],'values',[0,1])
    142                 md = checkfield(md,'fieldname','transient.isoceancoupling','numel',[1],'values',[0,1])
    143                 md = checkfield(md,'fieldname','transient.iscoupler','numel',[1],'values',[0,1])
    144                 md = checkfield(md,'fieldname','transient.amr_frequency','numel',[1],'>=',0,'NaN',1,'Inf',1)
    145                 md = checkfield(md,'fieldname','transient.requested_outputs','stringrow',1)
     131        md = checkfield(md,'fieldname','transient.issmb','numel',[1],'values',[0,1])
     132        md = checkfield(md,'fieldname','transient.ismasstransport','numel',[1],'values',[0,1])
     133        md = checkfield(md,'fieldname','transient.isstressbalance','numel',[1],'values',[0,1])
     134        md = checkfield(md,'fieldname','transient.isthermal','numel',[1],'values',[0,1])
     135        md = checkfield(md,'fieldname','transient.isgroundingline','numel',[1],'values',[0,1])
     136        md = checkfield(md,'fieldname','transient.isgia','numel',[1],'values',[0,1])
     137        md = checkfield(md,'fieldname','transient.isesa','numel',[1],'values',[0,1])
     138        md = checkfield(md,'fieldname','transient.isdamageevolution','numel',[1],'values',[0,1])
     139        md = checkfield(md,'fieldname','transient.ishydrology','numel',[1],'values',[0,1])
     140        md = checkfield(md,'fieldname','transient.ismovingfront','numel',[1],'values',[0,1]);
     141        md = checkfield(md,'fieldname','transient.isslr','numel',[1],'values',[0,1])
     142        md = checkfield(md,'fieldname','transient.isoceancoupling','numel',[1],'values',[0,1])
     143        md = checkfield(md,'fieldname','transient.iscoupler','numel',[1],'values',[0,1])
     144        md = checkfield(md,'fieldname','transient.amr_frequency','numel',[1],'>=',0,'NaN',1,'Inf',1)
     145        md = checkfield(md,'fieldname','transient.requested_outputs','stringrow',1)
    146146
    147                 if (solution!='TransientSolution') and (md.transient.iscoupling):
    148                     md.checkmessage("Coupling with ocean can only be done in transient simulations!")
    149                 if (md.transient.isdamageevolution and not hasattr(md.materials,'matdamageice')):
    150                     md.checkmessage("requesting damage evolution but md.materials is not of class matdamageice")
     147        if (solution!='TransientSolution') and (md.transient.iscoupling):
     148            md.checkmessage("Coupling with ocean can only be done in transient simulations!")
     149        if (md.transient.isdamageevolution and not hasattr(md.materials,'matdamageice')):
     150            md.checkmessage("requesting damage evolution but md.materials is not of class matdamageice")
    151151
    152                 return md
    153         # }}}
    154         def marshall(self,prefix,md,fid):    # {{{
    155                 WriteData(fid,prefix,'object',self,'fieldname','issmb','format','Boolean')
    156                 WriteData(fid,prefix,'object',self,'fieldname','ismasstransport','format','Boolean')
    157                 WriteData(fid,prefix,'object',self,'fieldname','isstressbalance','format','Boolean')
    158                 WriteData(fid,prefix,'object',self,'fieldname','isthermal','format','Boolean')
    159                 WriteData(fid,prefix,'object',self,'fieldname','isgroundingline','format','Boolean')
    160                 WriteData(fid,prefix,'object',self,'fieldname','isgia','format','Boolean')
    161                 WriteData(fid,prefix,'object',self,'fieldname','isesa','format','Boolean')
    162                 WriteData(fid,prefix,'object',self,'fieldname','isdamageevolution','format','Boolean')
    163                 WriteData(fid,prefix,'object',self,'fieldname','ishydrology','format','Boolean')
    164                 WriteData(fid,prefix,'object',self,'fieldname','ismovingfront','format','Boolean')
    165                 WriteData(fid,prefix,'object',self,'fieldname','isslr','format','Boolean')
    166                 WriteData(fid,prefix,'object',self,'fieldname','isoceancoupling','format','Boolean')
    167                 WriteData(fid,prefix,'object',self,'fieldname','iscoupler','format','Boolean')
    168                 WriteData(fid,prefix,'object',self,'fieldname','amr_frequency','format','Integer')
     152        return md
     153    # }}}
     154    def marshall(self,prefix,md,fid):    # {{{
     155        WriteData(fid,prefix,'object',self,'fieldname','issmb','format','Boolean')
     156        WriteData(fid,prefix,'object',self,'fieldname','ismasstransport','format','Boolean')
     157        WriteData(fid,prefix,'object',self,'fieldname','isstressbalance','format','Boolean')
     158        WriteData(fid,prefix,'object',self,'fieldname','isthermal','format','Boolean')
     159        WriteData(fid,prefix,'object',self,'fieldname','isgroundingline','format','Boolean')
     160        WriteData(fid,prefix,'object',self,'fieldname','isgia','format','Boolean')
     161        WriteData(fid,prefix,'object',self,'fieldname','isesa','format','Boolean')
     162        WriteData(fid,prefix,'object',self,'fieldname','isdamageevolution','format','Boolean')
     163        WriteData(fid,prefix,'object',self,'fieldname','ishydrology','format','Boolean')
     164        WriteData(fid,prefix,'object',self,'fieldname','ismovingfront','format','Boolean')
     165        WriteData(fid,prefix,'object',self,'fieldname','isslr','format','Boolean')
     166        WriteData(fid,prefix,'object',self,'fieldname','isoceancoupling','format','Boolean')
     167        WriteData(fid,prefix,'object',self,'fieldname','iscoupler','format','Boolean')
     168        WriteData(fid,prefix,'object',self,'fieldname','amr_frequency','format','Integer')
    169169
    170                 #process requested outputs
    171                 outputs = self.requested_outputs
    172                 indices = [i for i, x in enumerate(outputs) if x == 'default']
    173                 if len(indices) > 0:
    174                         outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
    175                         outputs    =outputscopy
    176                 WriteData(fid,prefix,'data',outputs,'name','md.transient.requested_outputs','format','StringArray')
    177         # }}}
     170        #process requested outputs
     171        outputs = self.requested_outputs
     172        indices = [i for i, x in enumerate(outputs) if x == 'default']
     173        if len(indices) > 0:
     174            outputscopy=outputs[0:max(0,indices[0]-1)]+self.defaultoutputs(md)+outputs[indices[0]+1:]
     175            outputs    =outputscopy
     176        WriteData(fid,prefix,'data',outputs,'name','md.transient.requested_outputs','format','StringArray')
     177    # }}}
  • issm/trunk-jpl/src/m/consistency/checkfield.m

    r23773 r23783  
    9898                for i=1:numel(fieldsize)
    9999                        if ~isnan(fieldsize(i)) & (size(field,i)~=fieldsize(i))
    100                                 md = checkmessage(md,getfieldvalue(options,'message',['field ''' fieldname ''' dimension # ' num2str(i) ' should be of size ' num2str(fieldsize(2))]));
     100                                md = checkmessage(md,getfieldvalue(options,'message',['field ''' fieldname ''' dimension # ' num2str(i) ' should be of size ' num2str(fieldsize(i))]));
    101101                        end
    102102                end
  • issm/trunk-jpl/src/m/consistency/checkfield.py

    r23761 r23783  
    77
    88def checkfield(md,*args):
    9         """
    10         CHECKFIELD - check field consistency
    11 
    12            Used to check model consistency.,
    13            Requires:
    14            'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname))
     9    """
     10    CHECKFIELD - check field consistency
     11
     12       Used to check model consistency.,
     13       Requires:
     14       'field' or 'fieldname' option. If 'fieldname' is provided, it will retrieve it from the model md. (md.(fieldname))
    1515             If 'field' is provided, it will assume the argument following 'field' is a numeric array.
    1616
    17            Available options:
    18               - NaN: 1 if check that there is no NaN
    19               - size: [lines cols], NaN for non checked dimensions, or 'universal' for any input type (nodal, element, time series, etc)
    20               - >:  greater than provided value
    21               - >=: greater or equal to provided value
    22               - <:  smallerthan provided value
    23               - <=: smaller or equal to provided value
    24               - < vec:  smallerthan provided values on each vertex
    25               - timeseries: 1 if check time series consistency (size and time)
    26               - values: cell of strings or vector of acceptable values
    27               - numel: list of acceptable number of elements
    28               - cell: 1 if check that is cell
    29               - empty: 1 if check that non empty
    30               - message: overloaded error message
    31 
    32            Usage:
    33               md = checkfield(md,fieldname,options);
    34         """
    35 
    36         #get options
    37         options=pairoptions(*args)
    38 
    39         #get field from model
    40         if options.exist('field'):
    41                 field=options.getfieldvalue('field')
    42                 fieldname=options.getfieldvalue('fieldname','no fieldname')
    43         else:
    44                 fieldname=options.getfieldvalue('fieldname')
    45                 fieldprefix=split(r'\[(.*?)\]',fieldname)[0]
    46                 fieldindexes=findall(r'\[(.*?)\]',fieldname)
    47                 field=attrgetter(fieldprefix)(md)
    48                 for index in fieldindexes:
    49                         try:
    50                                 field=field[index.strip("\'")]
    51                         except TypeError:
    52                                 field=field[int(index)] #looking for an index and not a key
     17       Available options:
     18          - NaN: 1 if check that there is no NaN
     19          - size: [lines cols], NaN for non checked dimensions, or 'universal' for any input type (nodal, element, time series, etc)
     20          - >:  greater than provided value
     21          - >=: greater or equal to provided value
     22          - <:  smallerthan provided value
     23          - <=: smaller or equal to provided value
     24          - < vec:  smallerthan provided values on each vertex
     25          - timeseries: 1 if check time series consistency (size and time)
     26          - values: cell of strings or vector of acceptable values
     27          - numel: list of acceptable number of elements
     28          - cell: 1 if check that is cell
     29          - empty: 1 if check that non empty
     30          - message: overloaded error message
     31
     32       Usage:
     33          md = checkfield(md,fieldname,options);
     34    """
     35
     36    #get options
     37    options=pairoptions(*args)
     38
     39    #get field from model
     40    if options.exist('field'):
     41        field=options.getfieldvalue('field')
     42        fieldname=options.getfieldvalue('fieldname','no fieldname')
     43    else:
     44        fieldname=options.getfieldvalue('fieldname')
     45        fieldprefix=split(r'\[(.*?)\]',fieldname)[0]
     46        fieldindexes=findall(r'\[(.*?)\]',fieldname)
     47        field=attrgetter(fieldprefix)(md)
     48        for index in fieldindexes:
     49            try:
     50                field=field[index.strip("\'")]
     51            except TypeError:
     52                field=field[int(index)] #looking for an index and not a key
    5353
    5454# that works for py2
    55 #               exec("field=md.{}".format(fieldname))
    56 #               exec("field=md.{}".format(fieldname),namespace)
    57 
    58 
    59         if isinstance(field,(bool,int,float)):
    60                 field=np.array([field])
    61 
    62         #check empty
    63         if options.exist('empty'):
    64                 if not field:
    65                         md = md.checkmessage(options.getfieldvalue('message',
    66                                 "field '%s' is empty" % fieldname))
    67 
    68         #Check size
    69         if options.exist('size'):
    70                 fieldsize=options.getfieldvalue('size')
    71                 if type(fieldsize) == str:
    72                         if m.strcmp(fieldsize,'universal'):
    73 
    74                                 #Check that vector size will not be confusing for ModelProcessorx
    75                                 if (md.mesh.numberofvertices==md.mesh.numberofelements):
    76                                         raise RuntimeError('number of vertices is the same as number of elements')
    77                                 elif (md.mesh.numberofvertices+1==md.mesh.numberofelements):
    78                                         raise RuntimeError('number of vertices +1 is the same as number of elements')
    79                                 elif (md.mesh.numberofvertices==md.mesh.numberofelements+1):
    80                                         raise RuntimeError('number of vertices is the same as number of elements +1')
    81                                
    82                                 #Uniform field
    83                                 if (np.size(field,0)==1):
    84                                         if (np.shape(field,1)!=1):
    85                                                 md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
    86 
    87                                 #vertex oriented input, only one column allowed
    88                                 elif (np.shape(field,0)==md.mesh.numberofvertices):
    89                                         if (np.shape(field,1)!=1):
    90                                                 md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
    91 
    92                                 #element oriented input, one or more column (patch) is ok
    93                                 elif (np.shape(field,0)==md.mesh.numberofelements):
    94                                         pass
    95                                         #nothing to do here (either constant per element, or defined on nodes)
    96 
    97                                 #vertex time series
    98                                 elif (np.shape(field,0)==md.mesh.numberofvertices+1):
    99                                         if (np.shape(field,1)<=1):
    100                                                 md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
    101 
    102                                 #element time series
    103                                 elif (np.shape(field,0)==md.mesh.numberofelements+1):
    104                                         if (np.shape(field,1)<=1):
    105                                                 md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
    106 
    107                                 #else not supported
    108                                 else:
    109                                         md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
    110 
    111                         else:
    112                                 raise RuntimeError("fieldsize '{}' not supported yet".format(fieldsize))
    113 
    114                 else:
    115                         if len(fieldsize) == 1:
    116                                 if np.isnan(fieldsize[0]):
    117                                         pass
    118                                 elif np.ndim(field)==1:
    119                                         if not np.size(field)==fieldsize[0]:
    120                                                 md = md.checkmessage(options.getfieldvalue('message',"field {} size should be {}".format(fieldname,fieldsize[0])))
    121                                 else:
    122                                         try:
    123                                                 exec("md.{}=np.squeeze(field)".format(fieldname))
    124                                                 print(("{} had been squeezed if it was a matrix with only one column".format(fieldname)))
    125                                         except IndexError:
    126                                                 md = md.checkmessage(options.getfieldvalue('message',"field {} should have {} dimension".format(fieldname,len(fieldsize))))
    127                         elif len(fieldsize) == 2:
    128                                 if   np.isnan(fieldsize[0]):
    129                                         if not np.size(field,1)==fieldsize[1]:
    130                                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d columns" % (fieldname,fieldsize[1])))
    131                                 elif np.isnan(fieldsize[1]):
    132                                         if not np.size(field,0)==fieldsize[0]:
    133                                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have %d lines" % (fieldname,fieldsize[0])))
    134                                 elif fieldsize[1]==1:
    135                                         if (not np.size(field,0)==fieldsize[0]):
    136                                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
    137                                 else:
    138                                         if (not np.size(field,0)==fieldsize[0]) or (not np.size(field,1)==fieldsize[1]):
    139                                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' size should be %d x %d" % (fieldname,fieldsize[0],fieldsize[1])))
    140 
    141         #Check numel
    142         if options.exist('numel'):
    143                 fieldnumel=options.getfieldvalue('numel')
    144                 if (type(fieldnumel) == int and np.size(field) != fieldnumel) or (type(fieldnumel) == list and np.size(field) not in fieldnumel):
    145                         if   len(fieldnumel)==1:
    146                                 md = md.checkmessage(options.getfieldvalue('message',\
    147                                         "field '%s' size should be %d" % (fieldname,fieldnumel)))
    148                         elif len(fieldnumel)==2:
    149                                 md = md.checkmessage(options.getfieldvalue('message',\
    150                                         "field '%s' size should be %d or %d" % (fieldname,fieldnumel[0],fieldnumel[1])))
    151                         else:
    152                                 md = md.checkmessage(options.getfieldvalue('message',\
    153                                         "field '%s' size should be %s" % (fieldname,fieldnumel)))
    154 
    155         #check NaN
    156         if options.getfieldvalue('NaN',0):
    157                 if np.any(np.isnan(field)):
    158                         md = md.checkmessage(options.getfieldvalue('message',\
    159                                 "NaN values found in field '%s'" % fieldname))
    160 
    161 
    162         #check Inf
    163         if options.getfieldvalue('Inf',0):
    164                 if np.any(np.isinf(field)):
    165                         md = md.checkmessage(options.getfieldvalue('message',\
    166                                 "Inf values found in field '%s'" % fieldname))
    167 
    168 
    169         #check cell
    170         if options.getfieldvalue('cell',0):
    171                 if not isinstance(field,(tuple,list,dict)):
    172                         md = md.checkmessage(options.getfieldvalue('message',\
    173                                 "field '%s' should be a cell" % fieldname))
    174 
    175         #check values
    176         if options.exist('values'):
    177                 fieldvalues=options.getfieldvalue('values')
    178                 if False in m.ismember(field,fieldvalues):
    179                         if   len(fieldvalues)==1:
    180                                 md = md.checkmessage(options.getfieldvalue('message',\
    181                                         "field '%s' value should be '%s'"  % (fieldname,fieldvalues[0])))
    182                         elif len(fieldvalues)==2:
    183                                 md = md.checkmessage(options.getfieldvalue('message',\
    184                                         "field '%s' values should be '%s' or '%s'"  % (fieldname,fieldvalues[0],fieldvalues[1])))
    185                         else:
    186                                 md = md.checkmessage(options.getfieldvalue('message',\
    187                                         "field '%s' should have values in %s" % (fieldname,fieldvalues)))
    188 
    189         #check greater
    190         if options.exist('>='):
    191                 lowerbound = options.getfieldvalue('>=')
    192                 if type(lowerbound) is str:
    193                         lowerbound=attrgetter(lowerbound)(md)
    194                 if np.size(lowerbound)>1: #checking elementwise
    195                         if any(field<upperbound):
    196                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
    197                 else:
    198                         minval=np.nanmin(field)
    199                         if options.getfieldvalue('timeseries',0):
    200                                 minval=np.nanmin(field[:-1])
    201                         elif options.getfieldvalue('singletimeseries',0):
    202                                 if np.size(field)==1: #some singletimeseries are just one value
    203                                         minval=field
    204                                 else:
    205                                         minval=np.nanmin(field[0])
    206 
    207                         if minval<lowerbound:
    208                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
    209 
    210         if options.exist('>'):
    211                 lowerbound=options.getfieldvalue('>')
    212                 if type(lowerbound) is str:
    213                         lowerbound=attrgetter(lowerbound)(md)
    214                 if np.size(lowerbound)>1: #checking elementwise
    215                         if any(field<=upperbound):
    216                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
    217                 else:
    218                         minval=np.nanmin(field)
    219                         if options.getfieldvalue('timeseries',0) :
    220                                 minval=np.nanmin(field[:-1])
    221                         elif options.getfieldvalue('singletimeseries',0):
    222                                 if np.size(field)==1: #some singletimeseries are just one value
    223                                         minval=field
    224                                 else:
    225                                         minval=np.nanmin(field[0])
    226 
    227                         if minval<=lowerbound:
    228                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
    229 
    230         #check smaller
    231         if options.exist('<='):
    232                 upperbound=options.getfieldvalue('<=')
    233                 if type(upperbound) is str:
    234                         upperbound=attrgetter(upperbound)(md)
    235                 if np.size(upperbound)>1: #checking elementwise
    236                         if any(field>upperbound):
    237                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
    238                 else:
    239                         maxval=np.nanmax(field)
    240                         if options.getfieldvalue('timeseries',0):
    241                                 maxval=np.nanmax(field[:-1])
    242                         elif  options.getfieldvalue('singletimeseries',0):
    243                                 if np.size(field)==1: #some singletimeseries are just one value
    244                                         maxval=field
    245                                 else:
    246                                         maxval=np.nanmax(field[0])
    247                         elif hasattr(field, 'fov_forward_indices'):
    248                                 maxval=field.fov_forward_indices[0]
    249                         if maxval>upperbound:
    250                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
    251 
    252         if options.exist('<'):
    253                 upperbound=options.getfieldvalue('<')
    254                 if type(upperbound) is str:
    255                         upperbound=attrgetter(upperbound)(md)
    256                 if np.size(upperbound)>1: #checking elementwise
    257                         if any(field>=upperbound):
    258                                 md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
    259 
    260                 else:
    261                         maxval=np.nanmax(field)
    262                         if options.getfieldvalue('timeseries',0):
    263                                 maxval=np.nanmax(field[:-1])
    264                         elif options.getfieldvalue('singletimeseries',0):
    265                                 if np.size(field)==1: #some singletimeseries are just one value
    266                                         maxval=field.copy()
    267                                 else:
    268                                         maxval=np.nanmax(field[0])
    269 
    270                                 if maxval>=upperbound:
    271                                         md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
    272 
    273         #check file
    274         if options.getfieldvalue('file',0):
    275                 if not os.path.exists(field):
    276                         md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname,field))
    277 
    278         #Check row of strings
    279         if options.exist('stringrow'):
    280                 if not isinstance(field,list):
    281                         md = md.checkmessage(options.getfieldvalue('message',\
    282                                         "field '%s' should be a list" %fieldname))
    283 
    284         #Check forcings (size and times)
    285         if options.getfieldvalue('timeseries',0):
    286                 if np.size(field,0)==md.mesh.numberofvertices or np.size(field,0)==md.mesh.numberofelements:
    287                         if np.ndim(field)>1 and not np.size(field,1)==1:
    288                                 md = md.checkmessage(options.getfieldvalue('message',\
    289                                         "field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
    290                 elif np.size(field,0)==md.mesh.numberofvertices+1 or np.size(field,0)==md.mesh.numberofelements+1:
    291                         if np.ndim(field) > 1 and not all(field[-1,:]==np.sort(field[-1,:])):
    292                                 md = md.checkmessage(options.getfieldvalue('message',\
    293                                         "field '%s' columns should be sorted chronologically" % fieldname))
    294                         if np.ndim(field) > 1 and any(field[-1,0:-1]==field[-1,1:]):
    295                                 md = md.checkmessage(options.getfieldvalue('message',\
    296                                         "field '%s' columns must not contain duplicate timesteps" % fieldname))
    297                 else:
    298                         md = md.checkmessage(options.getfieldvalue('message',\
    299                                 "field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname))
    300 
    301         #Check single value forcings (size and times)
    302         if options.getfieldvalue('singletimeseries',0):
    303                 if np.size(field,0)==2:
    304                         if not all(field[-1,:]==np.sort(field[-1,:])):
    305                                 md = md.checkmessage(options.getfieldvalue('message',\
    306                                                 "field '%s' columns should be sorted chronologically" % fieldname))
    307                         if any(field[-1,0:-1]==field[-1,1:]):
    308                                 md = md.checkmessage(options.getfieldvalue('message',\
    309                                                 "field '%s' columns must not contain duplicate timesteps" % fieldname))
    310                 elif np.size(field,0) == 1:
    311                         if np.ndim(field) > 1 and not np.size(field,1) == 1:
    312                                 md = md.checkmessage(options.getfieldvalue('message',\
    313                                 "field '%s' should be either a scalar or have 2 lines" % fieldname))
    314                 else:
    315                                 md = md.checkmessage(options.getfieldvalue('message',\
    316                                 "field '%s' should have 2 lines or be a scalar" % fieldname))
    317 
    318         return md
     55#        exec("field=md.{}".format(fieldname))
     56#        exec("field=md.{}".format(fieldname),namespace)
     57
     58
     59    if isinstance(field,(bool,int,float)):
     60        field=np.array([field])
     61
     62    #check empty
     63    if options.exist('empty'):
     64        if not field:
     65            md = md.checkmessage(options.getfieldvalue('message',
     66                "field '%s' is empty" % fieldname))
     67
     68    #Check size
     69    if options.exist('size'):
     70        fieldsize=options.getfieldvalue('size')
     71        if type(fieldsize) == str:
     72            if m.strcmp(fieldsize,'universal'):
     73
     74                #Check that vector size will not be confusing for ModelProcessorx
     75                if (md.mesh.numberofvertices==md.mesh.numberofelements):
     76                    raise RuntimeError('number of vertices is the same as number of elements')
     77                elif (md.mesh.numberofvertices+1==md.mesh.numberofelements):
     78                    raise RuntimeError('number of vertices +1 is the same as number of elements')
     79                elif (md.mesh.numberofvertices==md.mesh.numberofelements+1):
     80                    raise RuntimeError('number of vertices is the same as number of elements +1')
     81               
     82                #Uniform field
     83                if (np.size(field,0)==1):
     84                    if (np.shape(field)[1]!=1):
     85                        md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
     86
     87                #vertex oriented input, only one column allowed
     88                elif (np.shape(field)[0]==md.mesh.numberofvertices):
     89                    if (np.shape(field)[1]!=1):
     90                        md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
     91
     92                #element oriented input, one or more column (patch) is ok
     93                elif (np.shape(field)[0]==md.mesh.numberofelements):
     94                    pass
     95                    #nothing to do here (either constant per element, or defined on nodes)
     96
     97                #vertex time series
     98                elif (np.shape(field)[0]==md.mesh.numberofvertices+1):
     99                    if (np.shape(field)[1]<=1):
     100                        md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
     101
     102                #element time series
     103                elif (np.shape(field)[0]==md.mesh.numberofelements+1):
     104                    if (np.shape(field)[1]<=1):
     105                        md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
     106
     107                #else not supported
     108                else:
     109                    md = md.checkmessage(options.getfieldvalue('message',"field '{}' is not supported".format(fieldname)))
     110
     111            else:
     112                raise RuntimeError("fieldsize '{}' not supported yet".format(fieldsize))
     113
     114        else:
     115            for i in range(np.size(fieldsize)):
     116                if (not np.isnan(fieldsize[i])) and (np.shape(field)[i] != fieldsize[i]):
     117                    md = md.checkmessage(options.getfieldvalue('message',"field {} dimension # {} should be of size {}".format(fieldname,i,fieldsize[i])))
     118
     119    #Check numel
     120    if options.exist('numel'):
     121        fieldnumel=options.getfieldvalue('numel')
     122        if (type(fieldnumel) == int and np.size(field) != fieldnumel) or (type(fieldnumel) == list and np.size(field) not in fieldnumel):
     123            if   len(fieldnumel)==1:
     124                md = md.checkmessage(options.getfieldvalue('message',\
     125                    "field '%s' size should be %d" % (fieldname,fieldnumel)))
     126            elif len(fieldnumel)==2:
     127                md = md.checkmessage(options.getfieldvalue('message',\
     128                    "field '%s' size should be %d or %d" % (fieldname,fieldnumel[0],fieldnumel[1])))
     129            else:
     130                md = md.checkmessage(options.getfieldvalue('message',\
     131                    "field '%s' size should be %s" % (fieldname,fieldnumel)))
     132
     133    #check NaN
     134    if options.getfieldvalue('NaN',0):
     135        if np.any(np.isnan(field)):
     136            md = md.checkmessage(options.getfieldvalue('message',\
     137                "NaN values found in field '%s'" % fieldname))
     138
     139
     140    #check Inf
     141    if options.getfieldvalue('Inf',0):
     142        if np.any(np.isinf(field)):
     143            md = md.checkmessage(options.getfieldvalue('message',\
     144                "Inf values found in field '%s'" % fieldname))
     145
     146
     147    #check cell
     148    if options.getfieldvalue('cell',0):
     149        if not isinstance(field,(tuple,list,dict)):
     150            md = md.checkmessage(options.getfieldvalue('message',\
     151                "field '%s' should be a cell" % fieldname))
     152
     153    #check values
     154    if options.exist('values'):
     155        fieldvalues=options.getfieldvalue('values')
     156        if False in m.ismember(field,fieldvalues):
     157            if   len(fieldvalues)==1:
     158                md = md.checkmessage(options.getfieldvalue('message',\
     159                    "field '%s' value should be '%s'"  % (fieldname,fieldvalues[0])))
     160            elif len(fieldvalues)==2:
     161                md = md.checkmessage(options.getfieldvalue('message',\
     162                    "field '%s' values should be '%s' or '%s'"  % (fieldname,fieldvalues[0],fieldvalues[1])))
     163            else:
     164                md = md.checkmessage(options.getfieldvalue('message',\
     165                    "field '%s' should have values in %s" % (fieldname,fieldvalues)))
     166
     167    #check greater
     168    if options.exist('>='):
     169        lowerbound = options.getfieldvalue('>=')
     170        if type(lowerbound) is str:
     171            lowerbound=attrgetter(lowerbound)(md)
     172        if np.size(lowerbound)>1: #checking elementwise
     173            if any(field<upperbound):
     174                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
     175        else:
     176            minval=np.nanmin(field)
     177            if options.getfieldvalue('timeseries',0):
     178                minval=np.nanmin(field[:-1])
     179            elif options.getfieldvalue('singletimeseries',0):
     180                if np.size(field)==1: #some singletimeseries are just one value
     181                    minval=field
     182                else:
     183                    minval=np.nanmin(field[0])
     184
     185            if minval<lowerbound:
     186                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
     187
     188    if options.exist('>'):
     189        lowerbound=options.getfieldvalue('>')
     190        if type(lowerbound) is str:
     191            lowerbound=attrgetter(lowerbound)(md)
     192        if np.size(lowerbound)>1: #checking elementwise
     193            if any(field<=upperbound):
     194                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
     195        else:
     196            minval=np.nanmin(field)
     197            if options.getfieldvalue('timeseries',0) :
     198                minval=np.nanmin(field[:-1])
     199            elif options.getfieldvalue('singletimeseries',0):
     200                if np.size(field)==1: #some singletimeseries are just one value
     201                    minval=field
     202                else:
     203                    minval=np.nanmin(field[0])
     204
     205            if minval<=lowerbound:
     206                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values above %d" % (fieldname,lowerbound)))
     207
     208    #check smaller
     209    if options.exist('<='):
     210        upperbound=options.getfieldvalue('<=')
     211        if type(upperbound) is str:
     212            upperbound=attrgetter(upperbound)(md)
     213        if np.size(upperbound)>1: #checking elementwise
     214            if any(field>upperbound):
     215                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
     216        else:
     217            maxval=np.nanmax(field)
     218            if options.getfieldvalue('timeseries',0):
     219                maxval=np.nanmax(field[:-1])
     220            elif  options.getfieldvalue('singletimeseries',0):
     221                if np.size(field)==1: #some singletimeseries are just one value
     222                    maxval=field
     223                else:
     224                    maxval=np.nanmax(field[0])
     225            elif hasattr(field, 'fov_forward_indices'):
     226                maxval=field.fov_forward_indices[0]
     227            if maxval>upperbound:
     228                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
     229
     230    if options.exist('<'):
     231        upperbound=options.getfieldvalue('<')
     232        if type(upperbound) is str:
     233            upperbound=attrgetter(upperbound)(md)
     234        if np.size(upperbound)>1: #checking elementwise
     235            if any(field>=upperbound):
     236                md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
     237
     238        else:
     239            maxval=np.nanmax(field)
     240            if options.getfieldvalue('timeseries',0):
     241                maxval=np.nanmax(field[:-1])
     242            elif options.getfieldvalue('singletimeseries',0):
     243                if np.size(field)==1: #some singletimeseries are just one value
     244                    maxval=field.copy()
     245                else:
     246                    maxval=np.nanmax(field[0])
     247
     248                if maxval>=upperbound:
     249                    md = md.checkmessage(options.getfieldvalue('message',"field '%s' should have values below %d" % (fieldname,upperbound)))
     250
     251    #check file
     252    if options.getfieldvalue('file',0):
     253        if not os.path.exists(field):
     254            md = md.checkmessage("file provided in '%s': '%s' does not exist" % (fieldname,field))
     255
     256    #Check row of strings
     257    if options.exist('stringrow'):
     258        if not isinstance(field,list):
     259            md = md.checkmessage(options.getfieldvalue('message',\
     260                    "field '%s' should be a list" %fieldname))
     261
     262    #Check forcings (size and times)
     263    if options.getfieldvalue('timeseries',0):
     264        if np.size(field,0)==md.mesh.numberofvertices or np.size(field,0)==md.mesh.numberofelements:
     265            if np.ndim(field)>1 and not np.size(field,1)==1:
     266                md = md.checkmessage(options.getfieldvalue('message',\
     267                    "field '%s' should have only one column as there are md.mesh.numberofvertices lines" % fieldname))
     268        elif np.size(field,0)==md.mesh.numberofvertices+1 or np.size(field,0)==md.mesh.numberofelements+1:
     269            if np.ndim(field) > 1 and not all(field[-1,:]==np.sort(field[-1,:])):
     270                md = md.checkmessage(options.getfieldvalue('message',\
     271                    "field '%s' columns should be sorted chronologically" % fieldname))
     272            if np.ndim(field) > 1 and any(field[-1,0:-1]==field[-1,1:]):
     273                md = md.checkmessage(options.getfieldvalue('message',\
     274                    "field '%s' columns must not contain duplicate timesteps" % fieldname))
     275        else:
     276            md = md.checkmessage(options.getfieldvalue('message',\
     277                "field '%s' should have md.mesh.numberofvertices or md.mesh.numberofvertices+1 lines" % fieldname))
     278
     279    #Check single value forcings (size and times)
     280    if options.getfieldvalue('singletimeseries',0):
     281        if np.size(field,0)==2:
     282            if not all(field[-1,:]==np.sort(field[-1,:])):
     283                md = md.checkmessage(options.getfieldvalue('message',\
     284                        "field '%s' columns should be sorted chronologically" % fieldname))
     285            if any(field[-1,0:-1]==field[-1,1:]):
     286                md = md.checkmessage(options.getfieldvalue('message',\
     287                        "field '%s' columns must not contain duplicate timesteps" % fieldname))
     288        elif np.size(field,0) == 1:
     289            if np.ndim(field) > 1 and not np.size(field,1) == 1:
     290                md = md.checkmessage(options.getfieldvalue('message',\
     291                "field '%s' should be either a scalar or have 2 lines" % fieldname))
     292        else:
     293                md = md.checkmessage(options.getfieldvalue('message',\
     294                "field '%s' should have 2 lines or be a scalar" % fieldname))
     295
     296    return md
Note: See TracChangeset for help on using the changeset viewer.