Index: /issm/trunk-jpl/test/NightlyRun/IdFromString.m
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/IdFromString.m	(revision 12630)
+++ /issm/trunk-jpl/test/NightlyRun/IdFromString.m	(revision 12631)
@@ -22,5 +22,5 @@
 %return if no test found
 if isempty(ids_raw),
-	disp(['No test matches ''' string '' ]);
+	disp(['No test matches ''' string '''' ]);
 	return
 end
Index: /issm/trunk-jpl/test/NightlyRun/IdFromString.py
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/IdFromString.py	(revision 12631)
+++ /issm/trunk-jpl/test/NightlyRun/IdFromString.py	(revision 12631)
@@ -0,0 +1,35 @@
+#! /usr/bin/env python
+"""IDFROMSTRING - output ids from a given string"""
+#
+#   Usage:
+#      ids=IdFromString(string);
+#
+#   Examples:
+#      ids=IdFromString('Parallel');
+#      ids=IdFromString('79North');
+
+from IdToName import IdToName
+
+def IdFromString(string):
+
+	#Check input
+	if not isinstance(string,str):
+		raise TypeError('IdFromString error message: input argument is not a string.')
+
+	#Get the dictionary and scan for matches
+	idnames=IdToName(0)
+	ids=[item[0] for item in idnames.iteritems() if string in item[1]]
+
+	#Return if no test found
+	if not ids:
+		print "No test matches '%s'." % string
+		return ids
+
+	#Display names
+	ids.sort()
+	print "%d tests match '%s':" % (len(ids),string)
+	for id in ids:
+		print "   %d : %s" % (id,idnames[id])
+
+	return ids
+
Index: /issm/trunk-jpl/test/NightlyRun/IdToName.py
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/IdToName.py	(revision 12631)
+++ /issm/trunk-jpl/test/NightlyRun/IdToName.py	(revision 12631)
@@ -0,0 +1,327 @@
+#! /usr/bin/env python
+"""IDTONAME- return name of test"""
+#
+#   Usage:
+#      name=IdToName(id);
+
+def IdToName(id):
+	idname={
+		101 : 'SquareShelfConstrainedDiagM2dSerial',
+		102 : 'SquareShelfConstrainedDiagM2dParallel',
+		103 : 'SquareShelfConstrainedDiagM3dSerial',
+		104 : 'SquareShelfConstrainedDiagM3dParallel',
+		105 : 'SquareShelfConstrainedDiagP3dSerial',
+		106 : 'SquareShelfConstrainedDiagP3dParallel',
+		107 : 'SquareShelfConstrainedDiagS3dSerial',
+		108 : 'SquareShelfConstrainedDiagS3dParallel',
+		109 : 'SquareShelfConstrainedProg2dSerial',
+		110 : 'SquareShelfConstrainedProg2dParallel',
+		111 : 'SquareShelfConstrainedProg2dDGSerial',
+		112 : 'SquareShelfConstrainedProg2dDGParallel',
+		113 : 'SquareShelfConstrainedProg3dSerial',
+		114 : 'SquareShelfConstrainedProg3dParallel',
+		115 : 'SquareShelfConstrainedTherSteaSerial',
+		116 : 'SquareShelfConstrainedTherSteaParallel',
+		117 : 'SquareShelfConstrainedTherTranSerial',
+		118 : 'SquareShelfConstrainedTherTranParallel',
+		119 : 'SquareShelfConstrainedTranM2dSerial',
+		120 : 'SquareShelfConstrainedTranM2dParallel',
+		121 : 'SquareShelfConstrainedTranP3dSerial',
+		122 : 'SquareShelfConstrainedTranP3dParallel',
+		123 : 'SquareShelfConstrainedSurfSlop2dSerial',
+		124 : 'SquareShelfConstrainedSurfSlop2dParallel',
+		125 : 'SquareShelfConstrainedSurfSlop3dSerial',
+		126 : 'SquareShelfConstrainedSurfSlope3dParallel',
+		127 : 'SquareShelfConstrainedBedSlop2dSerial',
+		128 : 'SquareShelfConstrainedBedSlop2dParallel',
+		129 : 'SquareShelfConstrainedBedSlop3dSerial',
+		130 : 'SquareShelfConstrainedBedSlop3dParallel',
+		131 : 'SquareShelfConstrainedBalThic2dSerial',
+		132 : 'SquareShelfConstrainedBalThic2dParallel',
+		133 : 'SquareShelfConstrainedBalThic3dSerial',
+		134 : 'SquareShelfConstrainedBalThic3dParallel',
+		135 : 'SquareShelfConstrainedBalThic2dDGSerial',
+		136 : 'SquareShelfConstrainedBalThic2dDGParallel',
+		137 : 'SquareBamgMesh',
+		139 : 'SquareShelfConstrainedEnthalpySteaSerial',
+		140 : 'SquareShelfConstrainedEnthalpySteaParallel',
+		141 : 'SquareShelfConstrainedEnthalpyTranSerial',
+		142 : 'SquareShelfConstrainedEnthalpyTranParallel',
+		143 : 'SquareShelfConstrainedTransP3dEnthSerial',
+		144 : 'SquareShelfConstrainedTransP3dEnthParallel',
+		201 : 'SquareShelfDiagM2dSerial',
+		202 : 'SquareShelfDiagM2dParallel',
+		203 : 'SquareShelfDiagM3dSerial',
+		204 : 'SquareShelfDiagM3dParallel',
+		205 : 'SquareShelfDiagP3dSerial',
+		206 : 'SquareShelfDiagP3dParallel',
+		207 : 'SquareShelfDiagS3dSerial',
+		208 : 'SquareShelfDiagS3dParallel',
+		209 : 'SquareShelfDiagMP3dPenaltiesSerial',
+		210 : 'SquareShelfDiagMP3dPenaltiesParallel',
+		211 : 'SquareShelfTherSteaSerial',
+		212 : 'SquareShelfTherSteaParallel',
+		213 : 'SquareShelfTherTranSerial',
+		214 : 'SquareShelfTherTranParallel',
+		215 : 'SquareShelfTranM2dSerial',
+		216 : 'SquareShelfTranM2dParallel',
+		217 : 'SquareShelfTranM3dSerial',
+		218 : 'SquareShelfTranM3dParallel',
+		219 : 'SquareShelfTranP3dSerial',
+		220 : 'SquareShelfTranP3dParallel',
+		221 : 'SquareShelfTranS3dSerial',
+		222 : 'SquareShelfTranS3dParallel',
+		223 : 'SquareShelfCMBM2dSerial',
+		224 : 'SquareShelfCMBM2dParallel',
+		225 : 'SquareShelfCMBM3dSerial',
+		226 : 'SquareShelfCMBM3dParallel',
+		227 : 'SquareShelfCMBP3dSerial',
+		228 : 'SquareShelfCMBP3dParallel',
+		229 : 'SquareShelfCMBS3dSerial',
+		230 : 'SquareShelfCMBS3dParallel',
+		231 : 'SquareShelfDiagM2dRiftSerial',
+		232 : 'SquareShelfDiagM2dRiftParallel',
+		233 : 'SquareShelfConstrainedSerial',
+		234 : 'SquareShelfConstrainedParallel',
+		235 : 'SquareShelfConstrainedDakotaBSerial',
+		236 : 'SquareShelfConstrainedDakotaBParallel',
+		237 : 'SquareShelfDiagMP3dTilingSerial',
+		238 : 'SquareShelfDiagMP3dTilingParallel',
+		239 : 'SquareShelfDiagPS3dTilingSerial',
+		240 : 'SquareShelfDiagPS3dTilingParallel',
+		241 : 'SquareShelfDiagMS3dTilingSerial',
+		242 : 'SquareShelfDiagMS3dTilingParallel',
+		243 : 'SquareShelfDiagM2dTransientIncrHydroSerial',
+		244 : 'SquareShelfDiagM2dTransientIncrHydroParallel',
+		245 : 'SquareShelfDiagM2dTransientIncrNonHydroSerial',
+		246 : 'SquareShelfDiagM2dTransientIncrNonHydroParallel',
+		247 : 'SquareShelfDiagP3dTransientIncrHydroSerial',
+		248 : 'SquareShelfDiagP3dTransientIncrHydroParallel',
+		249 : 'SquareShelfDiagP3dTransientIncrNonHydroSerial',
+		250 : 'SquareShelfDiagP3dTransientIncrNonHydroParallel',
+		251 : 'SquareShelfTranCflM2dSerial',
+		252 : 'SquareShelfTranCflM2dParallel',
+		253 : 'SquareShelfTranCflP3dSerial',
+		254 : 'SquareShelfTranCflP3dParallel',
+		255 : 'SquareShelfTranForceNeg2dSerial',
+		256 : 'SquareShelfTranForceNeg2dParallel',
+		257 : 'SquareShelfTranForcePos2dSerial',
+		258 : 'SquareShelfTranForcePos2dParallel',
+		259 : 'SquareShelfTranForceNeg3dSerial',
+		260 : 'SquareShelfTranForceNeg3dParallel',
+		261 : 'SquareShelfTranForcePos3dSerial',
+		262 : 'SquareShelfTranForcePos3dParallel',
+		263 : 'SquareShelfTherTranForcTempSerial',
+		264 : 'SquareShelfTherTranForcTempParallel',
+		265 : 'SquareShelfTranP3dForcTempSerial',
+		266 : 'SquareShelfTranP3dForcTempParallel',
+		267 : 'SquareShelfTranForceNeg2dDakotaSamp',
+   	268 : 'SquareShelfTranForceNeg2dDakotaLocal',
+		301 : 'SquareSheetConstrainedDiagM2dSerial',
+		302 : 'SquareSheetConstrainedDiagM2dParallel',
+		303 : 'SquareSheetConstrainedDiagH2dSerial',
+		304 : 'SquareSheetConstrainedDiagH2dParallel',
+		305 : 'SquareSheetConstrainedDiagHM2dSerial',
+		306 : 'SquareSheetConstrainedDiagHM2dParallel',
+		307 : 'SquareSheetConstrainedDiagM3dSerial',
+		308 : 'SquareSheetConstrainedDiagM3dParallel',
+		309 : 'SquareSheetConstrainedDiagH3dSerial',
+		310 : 'SquareSheetConstrainedDiagH3dParallel',
+		311 : 'SquareSheetConstrainedDiagHM3dSerial',
+		312 : 'SquareSheetConstrainedDiagHM3dParallel',
+		313 : 'SquareSheetConstrainedDiagP3dSerial',
+		314 : 'SquareSheetConstrainedDiagP3dParallel',
+		315 : 'SquareSheetConstrainedDiagS3dSerial',
+		316 : 'SquareSheetConstrainedDiagS3dParallel',
+		317 : 'SquareSheetConstrainedProg2dSerial',
+		318 : 'SquareSheetConstrainedProg2dParallel',
+		319 : 'SquareSheetConstrainedProg2dDGSerial',
+		320 : 'SquareSheetConstrainedProg2dDGParallel',
+		321 : 'SquareSheetConstrainedProg3dSerial',
+		322 : 'SquareSheetConstrainedProg3dParallel',
+		323 : 'SquareSheetConstrainedTherSteaSerial',
+		324 : 'SquareSheetConstrainedTherSteaParallel',
+		325 : 'SquareSheetConstrainedTherTranSerial',
+		326 : 'SquareSheetConstrainedTherTranParallel',
+		327 : 'SquareSheetConstrainedTranH2dSerial',
+		328 : 'SquareSheetConstrainedTranH2dParallel',
+		329 : 'SquareSheetConstrainedTranH3dSerial',
+		330 : 'SquareSheetConstrainedTranH3dParallel',
+		331 : 'SquareSheetConstrainedTranM2dSerial',
+		332 : 'SquareSheetConstrainedTranM2dParallel',
+		333 : 'SquareSheetConstrainedTranP3dSerial',
+		334 : 'SquareSheetConstrainedTranP3dParallel',
+		335 : 'SquareSheetConstrainedSteaH3dSerial',
+		336 : 'SquareSheetConstrainedSteaH3dParallel',
+		337 : 'SquareSheetConstrainedCMDragM2dSerial',
+		338 : 'SquareSheetConstrainedCMDragM2dParallel',
+		339 : 'SquareSheetConstrainedCMDragM3dSerial',
+		340 : 'SquareSheetConstrainedCMDragM3dParallel',
+		341 : 'SquareSheetConstrainedCMDragP3dSerial',
+		342 : 'SquareSheetConstrainedCMDragP3dParallel',
+		343 : 'SquareSheetConstrainedCMDragS3dSerial',
+		344 : 'SquareSheetConstrainedCMDragS3dParallel',
+		345 : 'SquareSheetConstrainedTranCflM2dSerial',
+		346 : 'SquareSheetConstrainedTranCflM2dParallel',
+		347 : 'SquareSheetConstrainedTranCflH3dSerial',
+		348 : 'SquareSheetConstrainedTranCflH3dParallel',
+		349 : 'SquareSheetConstrainedEnthalpySteaSerial',
+		350 : 'SquareSheetConstrainedEnthalpySteaParallel',
+		351 : 'SquareSheetConstrainedEnthalpyTranSerial',
+		352 : 'SquareSheetConstrainedEnthalpyTranParallel',
+		353 : 'SquareSheetConstrainedTransP3dEnthSerial',
+		354 : 'SquareSheetConstrainedTransP3dEnthParallel',
+		401 : 'SquareSheetShelfDiagM2dSerial',
+		402 : 'SquareSheetShelfDiagM2dParallel',
+		403 : 'SquareSheetShelfDiagM3dSerial',
+		404 : 'SquareSheetShelfDiagM3dParallel',
+		405 : 'SquareSheetShelfDiagP3dSerial',
+		406 : 'SquareSheetShelfDiagP3dParallel',
+		407 : 'SquareSheetShelfDiagS3dSerial',
+		408 : 'SquareSheetShelfDiagS3dParallel',
+		409 : 'SquareSheetShelfDiagMP3dPenaltiesSerial',
+		410 : 'SquareSheetShelfDiagMP3dPenaltiesParallel',
+		411 : 'SquareSheetShelfTherSteaSerial',
+		412 : 'SquareSheetShelfTherSteaParallel',
+		413 : 'SquareSheetShelfTherTranSerial',
+		414 : 'SquareSheetShelfTherTranParallel',
+		415 : 'SquareSheetShelfTranM2dSerial',
+		416 : 'SquareSheetShelfTranM2dParallel',
+		417 : 'SquareSheetShelfTranMP3dPenaltiesSerial',
+		418 : 'SquareSheetShelfTranMP3dPenaltiesParallel',
+		419 : 'SquareSheetShelfSteaM3dSerial',
+		420 : 'SquareSheetShelfSteaM3dParallel',
+		421 : 'SquareSheetShelfSteaP3dSerial',
+		422 : 'SquareSheetShelfSteaP3dParallel',
+		423 : 'SquareSheetShelfDiadM3dDakotaSerial',
+		424 : 'SquareSheetShelfDiadM3dDakotaParallel',
+		425 : 'SquareSheetShelfDiadM3dDakotaPartSerial',
+		426 : 'SquareSheetShelfDiadM3dDakotaPartParallel',
+		427 : 'SquareSheetShelfDiadM3dDakotaMassFluxSerial',
+		428 : 'SquareSheetShelfDiadM3dDakotaMassFluxParallel',
+		429 : 'SquareSheetShelfCMDragSteaM3dSerial',
+		430 : 'SquareSheetShelfCMDragSteaM3dParallel',
+		431 : 'SquareSheetShelfCMDragSteaP3dSerial',
+		432 : 'SquareSheetShelfCMDragSteaP3dParallel',
+		434 : 'SquareSheetShelfDiadM3dDakotaSamp',
+		435 : 'SquareSheetShelfDiadM3dDakotaAreaAverage',
+		437 : 'SquareSheetShelfDiagMP3dTilingSerial',
+		438 : 'SquareSheetShelfDiagMP3dTilingParallel',
+		439 : 'SquareSheetShelfDakotaScaledResponse',
+		440 : 'SquareSheetShelfDakotaScaledResponse',
+		441 : 'SquareSheetShelfDiagPS3dTilingSerial',
+		442 : 'SquareSheetShelfDiagPS3dTilingParallel',
+		443 : 'SquareSheetShelfDiagMS3dTilingSerial',
+		444 : 'SquareSheetShelfDiagMS3dTilingParallel',
+		445 : 'RoundSheetShelfGLMigrationM2dSerial',
+		446 : 'RoundSheetShelfGLMigrationM2dParallel',
+		447 : 'SquareSheetShelfGroundingLine2dAgressiceSerial',
+		448 : 'SquareSheetShelfGroundingLine2dAgressiceParallel',
+		449 : 'SquareSheetShelfGroundingLine2dSoftSerial',
+		450 : 'SquareSheetShelfGroundingLine2dSoftParallel',
+		451 : 'SquareSheetShelfGroundingLine3dAgressiceSerial',
+		452 : 'SquareSheetShelfGroundingLine3dAgressiceParallel',
+		453 : 'SquareSheetShelfGroundingLine3dSoftSerial',
+		454 : 'SquareSheetShelfGroundingLine3dSoftParallel',
+		455 : 'SquareSheetShelfDiagM2dNewtonSerial',
+		456 : 'SquareSheetShelfDiagM2dNewtonParallel',
+		457 : 'SquareSheetShelfDiagP3dNewtonSerial',
+		458 : 'SquareSheetShelfDiagP3dNewtonParallel',
+		459 : 'SquareSheetShelfDiagS3dNewtonSerial',
+		460 : 'SquareSheetShelfDiagS3dNewtonParallel',
+		461 : 'SquareSheetShelfSteaEnthalpyM3dSerial',
+		462 : 'SquareSheetShelfSteaEnthalpyM3dParallel',
+		463 : 'SquareSheetShelfSteaEnthalpyP3dSerial',
+		464 : 'SquareSheetShelfSteaEnthalpyP3dParallel',
+		501 : 'PigDiagM2dSerial',
+		502 : 'PigDiagM2dParallel',
+		503 : 'PigDiagP3dSerial',
+		504 : 'PigDiagP3dParallel',
+		505 : 'PigDiagS3dSerial',
+		506 : 'PigDiagS3dParallel',
+		507 : 'PigTranM2dSerial',
+		508 : 'PigTranM2dParallel',
+		509 : 'PigTranM3dSerial',
+		510 : 'PigTranM3dParallel',
+		511 : 'PigTranP3dSerial',
+		512 : 'PigTranP3dParallel',
+		513 : 'PigTranS3dSerial',
+		514 : 'PigTranS3dParallel',
+		515 : 'PigSteaM3dSerial',
+		516 : 'PigSteaM3dParallel',
+		517 : 'PigSteaP3dSerial',
+		518 : 'PigSteaP3dParallel',
+		519 : 'PigSteaS3dSerial',
+		520 : 'PigSteaS3dParallel',
+		521 : 'PigCMBS3dSerial',
+		522 : 'PigCMBS3dparallel',
+		523 : 'PigCMDragP3dSerial',
+		524 : 'PigCMDragP3dparallel',
+		525 : 'PigCMDragSteaM3dSerial',
+		526 : 'PigCMDragSteaM3dparallel',
+		527 : 'PigBamgMesh',
+		529 : 'PigTherTranSUPGSerial',
+		530 : 'PigTherTranSUPGParallel',
+		531 : 'PigTherSteaSUPGSerial',
+		532 : 'PigTherSteaSUPGParallel',
+		601 : '79NorthProg2dSerial',
+		602 : '79NorthProg2dParallel',
+		603 : '79NorthProg2dDGSerial',
+		604 : '79NorthProg2dDGParallel',
+		605 : '79NorthProg3dSerial',
+		606 : '79NorthProg3dParallel',
+		607 : '79NorthSurfSlop2dSerial',
+		608 : '79NorthSurfSlop2dParallel',
+		609 : '79NorthSurfSlop3dSerial',
+		610 : '79NorthSurfSlop3dParallel',
+		611 : '79NorthBedSlop2dSerial',
+		612 : '79NorthBedSlop2dParallel',
+		613 : '79NorthBedSlop3dSerial',
+		614 : '79NorthBedSlop3dParallel',
+		615 : '79NorthBalThic2dSerial',
+		616 : '79NorthBalThic2dParallel',
+		617 : '79NorthBalThic2dDGSerial',
+		618 : '79NorthBalThic2dDGParallel',
+		619 : '79NorthBalThic3dSerial',
+		620 : '79NorthBalThic3dParallel',
+		621 : '79NorthCMBalThic2dCGSerial',
+		622 : '79NorthCMBalThic2dCGParallel',
+		623 : '79NorthCMBalThic2dDGSerial',
+		624 : '79NorthCMBalThic2dDGParallel',
+		625 : '79NorthCMBalThicVxVyParallel',
+		626 : '79NorthCMBalThicVxVySerial',
+		1101 : 'ISMIPAPattyn',
+		1102 : 'ISMIPAStokes',
+		1103 : 'ISMIPBPattyn',
+		1104 : 'ISMIPBStokes',
+		1105 : 'ISMIPCPattyn',
+		1106 : 'ISMIPCStokes',
+		1107 : 'ISMIPDPattyn',
+		1108 : 'ISMIPDStokes',
+		1109 : 'ISMIPE',
+		1110 : 'ISMIPF',
+		1201 : 'EISMINTMassConservation',
+		1202 : 'EISMINTDiag1',
+		1203 : 'EISMINTDiag2',
+		1204 : 'EISMINTTran2',
+		1205 : 'EISMINTRoundIceSheetStaticHutter',
+		1206 : 'EISMINTRoundIceSheetStaticPattyn',
+		1207 : 'EISMINTRoundIceSheetStaticStokes',
+		1208 : 'EISMINTA',
+		1301 : 'ThermalMelting',
+		1302 : 'ThermalAdvection',
+		1303 : 'ThermalConduction',
+		1304 : 'ThermalGeothermalFlux',
+		1401 : 'AdaptiveMeshRefinement1',
+		1402 : 'AdaptiveMeshRefinement2',
+		1501 : 'SquareShelfTranSawTooth2d',
+		1502 : 'SquareShelfTranSawTooth3d',
+		1601 : 'SquareShelfM2dRotation',
+		1602 : 'SquareSheetShelfP3dRotation',
+	}
+
+	if not id == 0:
+		return idname.get(id,'N/A')
+	else:
+		return idname
+
Index: /issm/trunk-jpl/test/NightlyRun/runme.m
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/runme.m	(revision 12630)
+++ /issm/trunk-jpl/test/NightlyRun/runme.m	(revision 12631)
@@ -49,5 +49,5 @@
 if ~ismember(benchmark,{'all','nightly','ismip','eismint','thermal','mesh','validation','tranforcing'})
 	disp('runme warning: benchmark not supported, defaulting to test ''nightly''')
-	benchmark='nighlty';
+	benchmark='nightly';
 end
 % }}}
@@ -87,5 +87,5 @@
 test_ids=intersect(test_ids,list_ids);
 % }}}
-%GET exculde {{{1
+%GET exclude {{{1
 exclude_ids=getfieldvalue(options,'exclude',[]);
 exclude_ids=[exclude_ids];
@@ -126,5 +126,5 @@
 
 			if ~strcmp(oshostname(),'larsen');
-				error(['Nighlty run archives must be saved on "larsen" (hostname is "' oshostname() '")']);
+				error(['Nightly run archives must be saved on "larsen" (hostname is "' oshostname() '")']);
 			end
 			for k=1:length(field_names),
@@ -135,5 +135,5 @@
 			disp(sprintf(['File ./../Archives/' archive_name ' saved\n']));
 
-			%ELSE: CHECK TEST
+		%ELSE: CHECK TEST
 		else,
 
Index: /issm/trunk-jpl/test/NightlyRun/runme.py
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/runme.py	(revision 12631)
+++ /issm/trunk-jpl/test/NightlyRun/runme.py	(revision 12631)
@@ -0,0 +1,241 @@
+#! /usr/bin/env python
+"""RUNME - test deck for ISSM nightly runs"""
+#
+#   In a test deck directory (tests/Vertification/NightlyRun for example)
+#   The following command will launch all the existing tests:
+#   >> runme
+#   To run the tests 101 and 102:
+#   >> runme('id',[101 102])
+#   etc...
+#
+#   Available options:
+#      'id'            followed by the list of ids requested
+#      'exclude'       ids to be excluded from the test
+#      'benchmark'     'nightly' (nightly run/ daily run)
+#                      'ismip'  : validation of ismip-hom tests
+#                      'eismint': validation of eismint tests
+#                      'thermal': validation of thermal tests
+#                      'mesh'   : validation of mesh tests
+#                      ...
+#      'procedure'     'check' : run the test (default)
+#                      'update': update the archive
+#                      'model' : prepare the model but no test is run
+#
+#   Usage:
+#      md=runme(varargin);
+#
+#   Examples:
+#      runme;
+#      runme('exclude',101);
+#      md=runme('id',102,'procedure','model');
+
+import os
+import glob
+import socket
+import numpy
+import sys
+from IdToName import IdToName
+
+def runme(id=None,exclude=None,benchmark='nightly',procedure='check',output='none',rank=1,numprocs=1):
+
+	#Get ISSM_DIR variable
+	ISSM_DIR=os.environ['ISSM_DIR']
+	print 'ISSM_DIR =',ISSM_DIR
+
+	#Process options
+	#GET benchmark {{{1
+	if not benchmark.lower() in ['all','nightly','ismip','eismint','thermal','mesh','validation','tranforcing']:
+		print "runme warning: benchmark '%s' not supported, defaulting to test 'nightly'." % benchmark
+		benchmark='nightly'
+	# }}}
+	#GET procedure {{{1
+	if not procedure.lower() in ['check','update']:
+		print "runme warning: procedure '%s' not supported, defaulting to test 'check'." % procedure
+		procedure='check'
+	# }}}
+	#GET output {{{1
+	if not output.lower() in ['nightly','daily','none']:
+		print "runme warning: output '%s' not supported, defaulting to test 'none'." % output
+		output='none'
+	# }}}
+	#GET RANK and NUMPROCS for multithreaded runs {{{1
+	if (numprocs<rank):
+		numprocs=1
+	# }}}
+
+	print 'id =',id
+	print 'exclude =',exclude
+	print 'benchmark =',benchmark
+	print 'procedure =',procedure
+	print 'output =',output
+	print 'rank =',rank
+	print 'numprocs =',numprocs
+
+	#GET ids  {{{1
+#	flist=os.listdir('.')     #use dir, as it seems to act OS independent
+	flist=glob.glob('test*.m')    #File name must start with 'test' and must end by '.m'
+	list_ids=[] 
+	for file in flist:
+#		if file[:4] == 'test' and \    #File name must start with 'test'
+#		   file[-2:] == '.m' and \    #File name must end by '.m'
+#		   not file == 'test.m':    #File name must be different than 'test.m'
+		if not file == 'test.m':    #File name must be different than 'test.m'
+			list_ids.append(int(file[4:-2]))    #Keep test id only (skip 'test' and '.m')
+#	[i1,i2]=parallelrange(rank,numprocs,length(list_ids));               #Get tests for this cpu only
+#	list_ids=list_ids(i1:i2);
+	print 'list_ids =',list_ids
+
+	if id:
+		if isinstance(id,list):
+			test_ids=id
+		else:
+			test_ids=[id]
+		test_ids=set(test_ids).intersection(set(list_ids))
+	else:
+		test_ids=set(list_ids)
+	print 'test_ids after list =',test_ids
+	# }}}
+
+	#GET exclude {{{1
+	if exclude:
+		if isinstance(exclude,list):
+			exclude_ids=exclude
+		else:
+			exclude_ids=[exclude]
+		test_ids=test_ids.difference(set(exclude_ids))
+	print 'test_ids after exclude =',test_ids
+	# }}}
+
+	#Process Ids according to benchmarks {{{1
+	if   benchmark.lower() == 'nightly':
+		test_ids=test_ids.intersection(set(range(1,1000)))
+	elif benchmark.lower() == 'ismip':
+		test_ids=test_ids.intersection(set(range(1101,1200)))
+	elif benchmark.lower() == 'eismint':
+		test_ids=test_ids.intersection(set(range(1201,1300)))
+	elif benchmark.lower() == 'thermal':
+		test_ids=test_ids.intersection(set(range(1301,1400)))
+	elif benchmark.lower() == 'mesh':
+		test_ids=test_ids.intersection(set(range(1401,1500)))
+	elif benchmark.lower() == 'validation':
+		test_ids=test_ids.intersection(set(range(1001,2000)))
+	elif benchmark.lower() == 'tranforcing':
+		test_ids=test_ids.intersection(set(range(1501,1503)))
+	print 'test_ids after benchmark =',test_ids
+	test_ids=list(test_ids)
+	test_ids.sort()
+	print 'test_ids after sort =',test_ids
+	# }}}
+
+	#Loop over tests and launch sequence
+	root=os.getcwd()
+	for id in test_ids:
+		try:
+
+			#Execute test
+			os.chdir(root)
+			id_string=IdToName(id)
+			execfile('test'+str(id)+'.py')
+
+			#UPDATE ARCHIVE?
+			archive_name='Archive'+str(id)
+			if procedure.lower() == 'update':
+
+				if not socket.gethostname().lower().split('.')[0] == 'larsen':
+					raise RuntimeError('Nightly run archives must be saved on "larsen" (hostname is "'+socket.gethostname()+'")')
+				for k,fieldname in enumerate(field_names):
+					field=field_values[k]
+					exec(archive_name+'_field'+str(k)+' =  field')
+#				eval(['save ../Archives/' archive_name ' ' archive_name '_field*']);
+				print 'File ./../Archives/'+archive_name+' saved\n'
+
+			#ELSE: CHECK TEST
+			else:
+
+#				#load archive
+#				load(['../Archives/' archive_name ]);
+
+				for k,fieldname in enumerate(field_names):
+
+					try:
+						#Get field and tolerance
+						field=numpy.array(field_values[k],dtype=float)
+						tolerance=field_tolerances[k]
+
+						#compare to archive
+						exec('archive=numpy.array('+archive_name+'_field'+str(k)+',dtype=float)')
+						error_diff=max(abs(archive-field))/(max(abs(archive))+sys.float_info.epsilon)
+
+						#disp test result
+						if (error_diff>tolerance):
+							print 'ERROR   difference: %-7.2g > %7.2g test id: %i test name: %s field: %s' % \
+								(error_diff,tolerance,id,id_string,fieldname)
+						else:
+							print 'SUCCESS difference: %-7.2g < %7.2g test id: %i test name: %s field: %s' % \
+								(error_diff,tolerance,id,id_string,fieldname)
+
+					except Exception as me2:
+
+						#something went wrong, print failure message:
+						directory=os.getcwd().split('/')    #  not used?
+						message=me2
+						if   output.lower() == 'nightly':
+							fid=open(ISSM_DIR+'/nightlylog/matlaberror.log', 'a')
+							fid.write('%s' % message)
+							fid.write('\n------------------------------------------------------------------\n')
+							fid.close()
+							print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,fieldname)
+						elif output.lower() == 'daily':
+							fid=open(ISSM_DIR+'/dailylog/matlaberror.log', 'a')
+							fid.write('%s' % message)
+							fid.write('\n------------------------------------------------------------------\n')
+							fid.close()
+							print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,fieldname)
+						else:
+							print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,fieldname)
+							raise RuntimeError(me2)
+
+		except Exception as me:
+
+			#something went wrong, print failure message:
+			directory=os.getcwd().split('/')    #  not used?
+			message=me
+			if   output.lower() == 'nightly':
+				fid=open(ISSM_DIR+'/nightlylog/matlaberror.log', 'a')
+				fid.write('%s' % message)
+				fid.write('\n------------------------------------------------------------------\n')
+				fid.close()
+				print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,'N/A')
+			elif output.lower() == 'daily':
+				fid=open(ISSM_DIR+'/dailylog/matlaberror.log', 'a')
+				fid.write('%s' % message)
+				fid.write('\n------------------------------------------------------------------\n')
+				fid.close()
+				print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,'N/A')
+			else:
+				print 'FAILURE difference: N/A test id: %i test name: %s field: %s' % (id,id_string,'N/A')
+				raise RuntimeError(me)
+
+#	#output md if requested
+#	if nargout==1
+#		varargout{1}=md;
+#	end
+
+	return
+
+if __name__ == '__main__':
+	import argparse
+	parser = argparse.ArgumentParser(description='RUNME - test deck for ISSM nightly runs')
+	parser.add_argument('-i','--id', nargs='*', type=int, help='followed by the list of ids requested', default=[])
+	parser.add_argument('-e','--exclude', nargs='*', type=int, help='ids to be excluded from the test', default=[])
+	parser.add_argument('-b','--benchmark', help='nightly/ismip/eismint/thermal/mesh/...', default='nightly')
+	parser.add_argument('-p','--procedure', help='check/update', default='check')
+	parser.add_argument('-o','--output', help='nightly/daily/none', default='none')
+	parser.add_argument('-r','--rank', type=int, help='rank', default=1)
+	parser.add_argument('-n','--numprocs', type=int, help='numprocs', default=1)
+	args = parser.parse_args()
+
+	md = runme(args.id, args.exclude, args.benchmark, args.procedure, args.output, args.rank, args.numprocs)
+
+	exit(md)
+
Index: /issm/trunk-jpl/test/NightlyRun/test102.py
===================================================================
--- /issm/trunk-jpl/test/NightlyRun/test102.py	(revision 12630)
+++ /issm/trunk-jpl/test/NightlyRun/test102.py	(revision 12631)
@@ -4,6 +4,21 @@
 from parameterize import *
 
-md=model();
-md=triangle(md,'../Exp/Square.exp',50000);
-md=setmask(md,'all','');
+md=model()
+md=triangle(md,'../Exp/Square.exp',50000)
+md=setmask(md,'all','')
 md=parameterize(md,'../Par/SquareShelfConstrained.py')
+
+#Fields and tolerances to track changes
+field_names     =['Vx','Vy','Vel','Pressure',\
+	'StressTensorxx','StressTensoryy','StressTensorxy']
+field_tolerances=[1e-13,1e-13,1e-13,1e-13,\
+	1e-13,1e-13,1e-13]
+field_values=[\
+	[md.results.DiagnosticSolution.Vx],\
+	[md.results.DiagnosticSolution.Vy],\
+	[md.results.DiagnosticSolution.Vel],\
+	[md.results.DiagnosticSolution.Pressure],\
+	[md.results.DiagnosticSolution.StressTensorxx],\
+	[md.results.DiagnosticSolution.StressTensoryy],\
+	[md.results.DiagnosticSolution.StressTensorxy],\
+	]
