Skip to content

Commit c9823f1

Browse files
committed
New heliostat availabililty model to allow for multiple components and options for ordering repairs. Overall project input parameters still only set up for 1 component
1 parent 6162a6d commit c9823f1

12 files changed

+1551
-242
lines changed

app/project.cpp

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ parameters::parameters()
7878
helio_mtf.set( 12000, "helio_mtf", lk::vardata_t::NUMBER, false, "Heliostat mean time to failure", "hr", "Heliostat availability|Parameters" );
7979
heliostat_repair_cost.set( 300, "heliostat_repair_cost", lk::vardata_t::NUMBER, false, "Heliostat repair cost", "$", "Heliostat availability|Parameters" );
8080
om_staff_max_hours_week.set( 35, "om_staff_max_hours_week", lk::vardata_t::NUMBER, false, "Max O&M staff hours per week", "hr", "Heliostat availability|Parameters" );
81-
n_heliostats_sim.set( 1000, "n_heliostats_sim", lk::vardata_t::NUMBER, false, "Number of simulated heliostats", "-", "Heliostat availability|Parameters" );
81+
n_heliostats_sim.set( 8000, "n_heliostats_sim", lk::vardata_t::NUMBER, false, "Number of simulated heliostats", "-", "Heliostat availability|Parameters" );
8282
wash_units_per_hour.set( 45., "wash_units_per_hour", lk::vardata_t::NUMBER, false, "Heliostat wash rate", "1/crew-hr", "Optical degradation|Parameters" );
8383
wash_crew_max_hours_week.set( 70., "wash_crew_max_hours_week", lk::vardata_t::NUMBER, false, "Wash crew max hours per week", "hr", "Optical degradation|Parameters" );
8484
degr_per_hour.set( 1.e-7, "degr_per_hour", lk::vardata_t::NUMBER, false, "Reflectivity degradation rate", "1/hr", "Optical degradation|Parameters" );
@@ -1483,15 +1483,30 @@ bool Project::M()
14831483

14841484
solarfield_availability sfa;
14851485

1486-
sfa.m_settings.mf = m_parameters.helio_mtf.as_number();
1487-
sfa.m_settings.rep_min = 1.;
1488-
sfa.m_settings.rep_max = 100.;
1486+
sfa.m_settings.n_years = m_parameters.plant_lifetime.as_integer();
1487+
sfa.m_settings.step = 4.0;
1488+
1489+
sfa.m_settings.n_om_staff.assign(sfa.m_settings.n_years, m_variables.om_staff.as_number());
1490+
sfa.m_settings.max_hours_per_day = 9.;
1491+
sfa.m_settings.max_hours_per_week = m_parameters.om_staff_max_hours_week.as_number();
1492+
14891493
sfa.m_settings.n_helio = m_design_outputs.number_heliostats.as_integer();
1490-
sfa.m_settings.n_om_staff = m_variables.om_staff.as_integer();
1491-
sfa.m_settings.hr_prod = m_parameters.om_staff_max_hours_week.as_number();
1492-
sfa.m_settings.n_hr_sim = 8760 * 12;
1494+
sfa.m_settings.n_helio_sim = m_parameters.n_heliostats_sim.as_integer();
14931495
sfa.m_settings.seed = m_parameters.avail_seed.as_integer();
1494-
sfa.m_settings.n_helio_sim = 1000;
1496+
1497+
sfa.m_settings.is_fix_hours = true;
1498+
sfa.m_settings.sunrise = 6.9;
1499+
sfa.m_settings.sunset = 19.0;
1500+
1501+
sfa.m_settings.repair_order = MEAN_REPAIR_TIME;
1502+
sfa.m_settings.is_tracking = false;
1503+
1504+
1505+
sfa.m_settings.helio_performance.assign(sfa.m_settings.n_helio, 1.0);
1506+
helio_component_inputs comp(1.0, (double)m_parameters.helio_mtf.as_number(), 2.0, 1.0, 100.0, true, (double)m_parameters.heliostat_repair_cost.as_number());
1507+
sfa.m_settings.helio_components.push_back(comp);
1508+
1509+
14951510

14961511
//error if trying to simulate with no heliostats
14971512
if (m_design_outputs.number_heliostats.as_integer() <= 1)
@@ -1503,21 +1518,22 @@ bool Project::M()
15031518
sfa.simulate(sim_progress_handler);
15041519

15051520
//Calculate staff cost and repair cost
1506-
double ann_fact = 8760. / (double)sfa.m_settings.n_hr_sim;
1521+
sfa.m_results.heliostat_repair_cost_y1 = 0.0;
1522+
for (int c = 0; c < sfa.m_settings.helio_components.size(); c++)
1523+
sfa.m_results.heliostat_repair_cost_y1 += sfa.m_settings.helio_components[c].m_repair_cost * ( sfa.m_results.n_repairs_per_component[c] / sfa.m_settings.n_years); // Average yearly repair cost
15071524

1508-
sfa.m_results.n_repairs *= ann_fact; //annual repairs
1509-
sfa.m_results.heliostat_repair_cost_y1 = sfa.m_results.n_repairs * m_parameters.heliostat_repair_cost.as_number();
15101525

15111526
//lifetime costs
15121527
//treat heliostat repair costs as consuming reserve equipment paid for at the project outset
1513-
sfa.m_results.heliostat_repair_cost = calc_real_dollars(sfa.m_results.heliostat_repair_cost_y1);
1528+
double total_cost = sfa.m_results.heliostat_repair_cost_y1 * sfa.m_settings.n_years;
1529+
sfa.m_results.heliostat_repair_cost = calc_real_dollars(total_cost);
15141530

15151531
//assign outputs to project structure
15161532
m_solarfield_outputs.n_repairs.assign( sfa.m_results.n_repairs );
15171533
m_solarfield_outputs.staff_utilization.assign( sfa.m_results.staff_utilization );
15181534
m_solarfield_outputs.heliostat_repair_cost_y1.assign( sfa.m_results.heliostat_repair_cost_y1 );
15191535
m_solarfield_outputs.heliostat_repair_cost.assign( sfa.m_results.heliostat_repair_cost );
1520-
m_solarfield_outputs.avail_schedule.assign_vector( sfa.m_results.avail_schedule, sfa.m_results.n_avail_schedule );
1536+
m_solarfield_outputs.avail_schedule.assign_vector( sfa.m_results.avail_schedule);
15211537

15221538
is_sf_avail_valid = true;
15231539
return true;

app/scripting.cpp

Lines changed: 86 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ void _test(lk::invoke_t &cxt)
260260
P->m_variables.n_wash_crews.assign( 3 );
261261
P->m_variables.N_panels.assign( 16 );
262262

263-
P->m_parameters.solar_resource_file.assign( "/home/mike/workspace/dao-tk/deploy/samples/USA CA Daggett Barstow-daggett Ap (TMY3).csv" );
264-
263+
//P->m_parameters.solar_resource_file.assign( "/home/mike/workspace/dao-tk/deploy/samples/USA CA Daggett Barstow-daggett Ap (TMY3).csv" );
264+
P->m_parameters.solar_resource_file.assign("C:/Users/jmartine/Documents/Projects/dao-tk/deploy/samples/USA CA Daggett Barstow-daggett Ap (TMY3).csv");
265265
P->D();
266266
P->M();
267267
P->O();
@@ -582,60 +582,120 @@ void _simulate_solarfield(lk::invoke_t &cxt)
582582
{
583583
LK_DOC("simulate_solarfield", "Simulate the solar field availability over time due to heliostat failures. "
584584
"Table keys include: "
585-
"mean_time_to_failure, n_helio_actual, n_helio_simulated, n_om_staff, n_hr_sim, rng_seed, repair_min_downtime, "
586-
"rep_max_downtime, staff_productive_hr_week."
585+
"weibull_shape_param, weibull_scale_param, rep_mean_downtime, rep_min_downtime, rep_max_downtime, rep_good_as_new,"
586+
"n_helio_simulated, n_om_staff, n_year_sim, rng_seed, staff_productive_hr_week, model_time_step, repair_order."
587587
, "(table:inputs):table");
588588

589589
solarfield_availability SA;
590590

591591
lk::varhash_t *H = cxt.arg(0).hash();
592592

593+
593594
std::string error_msg;
594595
MainWindow &mw = MainWindow::Instance();
596+
595597
if( ! mw.GetProject()->Validate(Project::CALLING_SIM::HELIO_AVAIL, &error_msg) )
596598
{
597599
mw.Log( error_msg );
598600
return;
599601
}
600602

601-
SA.m_settings.mf = 12000;
602-
if (H->find("mean_time_to_failure") != H->end())
603-
SA.m_settings.mf = H->at("mean_time_to_failure")->as_integer();
603+
SA.m_settings.n_helio = mw.GetProject()->m_design_outputs.number_heliostats.as_integer();
604604

605-
SA.m_settings.n_helio = 9264;
606-
if (H->find("n_helio_actual") != H->end())
607-
SA.m_settings.n_helio = H->at("n_helio_actual")->as_integer();
608605

609-
SA.m_settings.n_helio_sim = 1000;
606+
SA.m_settings.n_helio_sim = 8000;
610607
if (H->find("n_helio_simulated") != H->end())
611608
SA.m_settings.n_helio_sim = H->at("n_helio_simulated")->as_integer();
612609

613-
SA.m_settings.n_om_staff = 5;
614-
if (H->find("n_om_staff") != H->end())
615-
SA.m_settings.n_om_staff = H->at("n_om_staff")->as_integer();
610+
SA.m_settings.n_years = 30;
611+
if (H->find("n_year_sim") != H->end())
612+
SA.m_settings.n_years = H->at("n_year_sim")->as_integer();
616613

617-
SA.m_settings.n_hr_sim = 105120;
618-
if (H->find("n_hr_sim") != H->end())
619-
SA.m_settings.n_hr_sim = H->at("n_hr_sim")->as_integer();
614+
double om_staff = 5;
615+
if (H->find("n_om_staff") != H->end())
616+
om_staff = H->at("n_om_staff")->as_integer();
617+
SA.m_settings.n_om_staff.assign(SA.m_settings.n_years, om_staff);
620618

621619
SA.m_settings.seed = 123;
622620
if (H->find("rng_seed") != H->end())
623621
SA.m_settings.seed = H->at("rng_seed")->as_integer();
624622

625-
SA.m_settings.rep_min = 1; //[hr]
626-
if (H->find("repair_min_downtime") != H->end())
627-
SA.m_settings.rep_min = H->at("repair_min_downtime")->as_number();
628623

629-
SA.m_settings.rep_max = 100; //[hr]
624+
SA.m_settings.max_hours_per_week = 35;
625+
if (H->find("staff_productive_hr_week") != H->end())
626+
SA.m_settings.max_hours_per_week = H->at("staff_productive_hr_week")->as_number();
627+
628+
SA.m_settings.step = 4.;
629+
if (H->find("model_time_step") != H->end())
630+
SA.m_settings.step = H->at("model_time_step")->as_number();
631+
632+
633+
//-- Heliostat component inputs
634+
double beta = 1.0;
635+
if (H->find("weibull_shape_param") != H->end())
636+
beta = H->at("weibull_shape_param")->as_integer();
637+
638+
double eta = 12000; //[hr]
639+
if (H->find("weibull_scale_param") != H->end())
640+
eta = H->at("weibull_scale_param")->as_integer();
641+
642+
double rep_mean = 2.;
643+
if (H->find("rep_mean_downtime") != H->end())
644+
rep_mean = H->at("rep_mean_downtime")->as_number();
645+
646+
double rep_min = 1; //[hr]
647+
if (H->find("rep_min_downtime") != H->end())
648+
rep_min = H->at("rep_min_downtime")->as_number();
649+
650+
double rep_max = 100; //[hr]
630651
if (H->find("rep_max_downtime") != H->end())
631-
SA.m_settings.rep_max = H->at("rep_max_downtime")->as_number();
652+
rep_max = H->at("rep_max_downtime")->as_number();
632653

633-
SA.m_settings.hr_prod = 35;
634-
if (H->find("staff_productive_hr_week") != H->end())
635-
SA.m_settings.hr_prod = H->at("staff_productive_hr_week")->as_number();
636-
654+
bool good_as_new = true;
655+
if (H->find("rep_good_as_new") != H->end())
656+
good_as_new = H->at("rep_good_as_new")->as_boolean();
657+
658+
helio_component_inputs component(beta, eta, rep_mean, rep_min, rep_max, good_as_new, 0.0);
659+
SA.m_settings.helio_components.push_back(component);
660+
661+
662+
//-- Repair ordering
663+
SA.m_settings.repair_order = MEAN_REPAIR_TIME;
664+
665+
if (H->find("repair_order") != H->end())
666+
{
667+
std::string ro = H->at("repair_order")->as_string();
668+
669+
if (ro == "failure_order")
670+
SA.m_settings.repair_order = FAILURE_ORDER;
671+
else if (ro == "performance")
672+
SA.m_settings.repair_order = PERFORMANCE;
673+
else if (ro == "repair_time")
674+
SA.m_settings.repair_order = REPAIR_TIME;
675+
else if (ro == "mean_repair_time")
676+
SA.m_settings.repair_order = MEAN_REPAIR_TIME;
677+
else if (ro == "random")
678+
SA.m_settings.repair_order = RANDOM;
679+
else
680+
mw.Log("Specified repair order not recognized. Valid inputs are 'failure_order', 'performance', 'repair_time', 'mean_repair_time', 'random'");
681+
}
682+
683+
684+
SA.m_settings.helio_performance.assign(SA.m_settings.n_helio, 1.0);
637685
SA.simulate();
638686

687+
688+
mw.Log(wxString::Format("Overall average availability: %0.3f ", SA.m_results.avg_avail));
689+
mw.Log(wxString::Format("Minimum availability: %0.3f ", SA.m_results.min_avail));
690+
691+
for (int c = 0; c < SA.m_settings.helio_components.size(); c++)
692+
mw.Log(wxString::Format("Component %d failures / repairs: %0.1f / %0.1f ", c, SA.m_results.n_failures_per_component[c], SA.m_results.n_repairs_per_component[c]));
693+
694+
695+
696+
697+
698+
639699
return;
640700

641701
}

build_vs2017/dao-tk_vs2017.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<ClCompile Include="..\app\project.cpp" />
2929
<ClCompile Include="..\app\scripting.cpp" />
3030
<ClCompile Include="..\app\scriptview.cpp" />
31+
<ClCompile Include="..\app\treeselect.cpp" />
3132
</ItemGroup>
3233
<ItemGroup>
3334
<ClInclude Include="..\app\daotk_app.h" />
@@ -36,6 +37,7 @@
3637
<ClInclude Include="..\app\project.h" />
3738
<ClInclude Include="..\app\scripting.h" />
3839
<ClInclude Include="..\app\scriptview.h" />
40+
<ClInclude Include="..\app\treeselect.h" />
3941
</ItemGroup>
4042
<ItemGroup>
4143
<ProjectReference Include="libcluster.vcxproj">

build_vs2017/libsolar.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020
</ItemGroup>
2121
<ItemGroup>
2222
<ClCompile Include="..\libsolar\solarfield_avail.cpp" />
23+
<ClCompile Include="..\libsolar\solarfield_heliostat.cpp" />
24+
<ClCompile Include="..\libsolar\solarfield_staff.cpp" />
2325
<ClCompile Include="..\libsolar\solarfield_structures.cpp" />
2426
</ItemGroup>
2527
<ItemGroup>
2628
<ClInclude Include="..\libsolar\solarfield_avail.h" />
29+
<ClInclude Include="..\libsolar\solarfield_heliostat.h" />
30+
<ClInclude Include="..\libsolar\solarfield_staff.h" />
2731
<ClInclude Include="..\libsolar\solarfield_structures.h" />
2832
</ItemGroup>
2933
<PropertyGroup Label="Globals">

0 commit comments

Comments
 (0)