@@ -1309,6 +1309,7 @@ def test_redrilling_costs(self):
13091309 def test_royalty_rate (self ):
13101310 royalties_output_name = 'Average Annual Royalty Cost'
13111311
1312+ zero_royalty_npv = None
13121313 for royalty_rate in [0 , 0.1 ]:
13131314 result = GeophiresXClient ().get_geophires_result (
13141315 ImmutableGeophiresInputParameters (
@@ -1345,6 +1346,9 @@ def test_royalty_rate(self):
13451346 self .assertEqual (58.88 , opex_result [royalties_output_name ]['value' ])
13461347 self .assertGreater (royalty_holder_npv_MUSD , 0 )
13471348
1349+ # Owner NPV is lower when royalty rate is non-zero
1350+ self .assertGreater (zero_royalty_npv , result .result ['ECONOMIC PARAMETERS' ]['Project NPV' ]['value' ])
1351+
13481352 royalties_cash_flow_MUSD = [
13491353 it * 1e-6
13501354 for it in _cash_flow_profile_row (
@@ -1362,3 +1366,65 @@ def test_royalty_rate(self):
13621366 if royalty_rate == 0.0 :
13631367 self .assertEqual (0 , opex_result [royalties_output_name ]['value' ])
13641368 self .assertEqual (0 , royalty_holder_npv_MUSD )
1369+ zero_royalty_npv = result .result ['ECONOMIC PARAMETERS' ]['Project NPV' ]['value' ]
1370+
1371+ def test_royalty_rate_escalation (self ):
1372+ royalties_output_name = 'Average Annual Royalty Cost'
1373+
1374+ base_royalty_rate = 0.05
1375+ escalation_rate = 0.01
1376+
1377+ for max_rate in [0.08 , 1.0 ]:
1378+ result = GeophiresXClient ().get_geophires_result (
1379+ ImmutableGeophiresInputParameters (
1380+ from_file_path = self ._get_test_file_path (
1381+ 'geophires_x_tests/generic-egs-case-2_sam-single-owner-ppa.txt'
1382+ ),
1383+ params = {
1384+ 'Royalty Rate' : base_royalty_rate ,
1385+ 'Royalty Rate Escalation' : escalation_rate ,
1386+ 'Royalty Rate Maximum' : max_rate ,
1387+ },
1388+ )
1389+ )
1390+ opex_result = result .result ['OPERATING AND MAINTENANCE COSTS (M$/yr)' ]
1391+
1392+ self .assertIsNotNone (opex_result [royalties_output_name ])
1393+ self .assertEqual ('MUSD/yr' , opex_result [royalties_output_name ]['unit' ])
1394+
1395+ total_opex_MUSD = opex_result ['Total operating and maintenance costs' ]['value' ]
1396+
1397+ opex_line_item_sum = 0
1398+ for line_item_names in [
1399+ 'Wellfield maintenance costs' ,
1400+ 'Power plant maintenance costs' ,
1401+ 'Water costs' ,
1402+ royalties_output_name ,
1403+ ]:
1404+ opex_line_item_sum += opex_result [line_item_names ]['value' ]
1405+
1406+ self .assertAlmostEqual (opex_line_item_sum , total_opex_MUSD , places = 4 )
1407+
1408+ project_lifetime_yrs = result .result ['ECONOMIC PARAMETERS' ]['Project lifetime' ]['value' ]
1409+
1410+ royalties_cash_flow_MUSD = [
1411+ it * 1e-6
1412+ for it in _cash_flow_profile_row (
1413+ result .result ['SAM CASH FLOW PROFILE' ], 'O&M production-based expense ($)'
1414+ )
1415+ ][1 :]
1416+
1417+ ppa_revenue_MUSD = [
1418+ it * 1e-6 for it in _cash_flow_profile_row (result .result ['SAM CASH FLOW PROFILE' ], 'PPA revenue ($)' )
1419+ ][1 :]
1420+
1421+ actual_royalty_rate = [None ] * len (ppa_revenue_MUSD )
1422+ for i in range (len (ppa_revenue_MUSD )):
1423+ actual_royalty_rate [i ] = royalties_cash_flow_MUSD [i ] / ppa_revenue_MUSD [i ]
1424+
1425+ max_expected_rate = (
1426+ max_rate if max_rate < 1.0 else base_royalty_rate + escalation_rate * (project_lifetime_yrs - 1 )
1427+ )
1428+
1429+ expected_last_year_revenue = ppa_revenue_MUSD [- 1 ] * max_expected_rate
1430+ self .assertAlmostEqual (expected_last_year_revenue , royalties_cash_flow_MUSD [- 1 ], places = 3 )
0 commit comments