within ${within};
model ${bldg.name}_${zone.name.replace(" ", "")}
  "This is the simulation model of ${bldg.name}_${zone.name.replace(" ", "")}"

  Annex60.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    calTSky=Annex60.BoundaryConditions.Types.SkyTemperatureCalculation.HorizontalRadiation,
    computeWetBulbTemperature=false,
    filNam="modelica://Annex60/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos")
    "Weather data reader"
    annotation (Placement(transformation(extent={{-98,52},{-78,72}})));
  Annex60.BoundaryConditions.SolarIrradiation.DiffusePerez HDifTil[${len(zone.orientation_wall)}](
    each outSkyCon=true,
    each outGroCon=true,
    til={${list_to_string(deg_to_rad_list(zone.tilt_wall))}},
    % if bldg.latitude is None:
    each  lat=0.87266462599716,
    % else:
    each  lat=${deg_to_rad(bldg.latitude)},
    % endif
    azi={${list_to_string(deg_to_rad_list(get_azimut(zone.orientation_wall)))}})
    "Calculates diffuse solar radiation on titled surface for all directions"
    annotation (Placement(transformation(extent={{-68,20},{-48,40}})));
  Annex60.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirTil[${len(zone.orientation_wall)}](
    til={${list_to_string(deg_to_rad_list(zone.tilt_wall))}},
    % if bldg.latitude is None:
    each  lat=0.87266462599716,
    % else:
    each  lat=${bldg.latitude},
    % endif
    azi={${list_to_string(deg_to_rad_list(get_azimut(zone.orientation_wall)))}})
    "Calculates direct solar radiation on titled surface for all directions"
    annotation (Placement(transformation(extent={{-68,52},{-48,72}})));
  Annex60.ThermalZones.ReducedOrder.SolarGain.CorrectionGDoublePane corGDoublePane(n=${len(zone.orientation_wall)}, UWin=${zone.ua_value_win/zone.area_win})
    "Correction factor for solar transmission"
    annotation (Placement(transformation(extent={{6,54},{26,74}})));
  Annex60.ThermalZones.ReducedOrder.RC.FourElements
  thermalZoneFourElements(
    redeclare package Medium = Modelica.Media.Air.SimpleAir,
    VAir=${zone.volume},
    alphaExt=${zone.alpha_comb_inner_ow},
    alphaWin=${zone.alpha_conv_inner_win},
    gWin=${zone.weighted_g_value},
    ratioWinConRad=${zone.windows[0].a_conv},
    nExt=1,
    RExt={${zone.r1_ow}},
    CExt={${zone.c1_ow}},
    alphaRad=${mean_alphaRad(zone)},
    AInt=${zone.area_iw},
    alphaInt=${zone.alpha_comb_iw},
    nInt=1,
    RInt={${zone.r1_iw}},
    CInt={${zone.c1_iw}},
    RWin=${zone.r1_win},
    RExtRem=${zone.r_rest_ow},
    AFloor=${zone.area_gf},
    alphaFloor=${zone.alpha_conv_inner_gf},
    nFloor=1,
    RFloor={${zone.r1_gf}},
    RFloorRem=${zone.r_rest_gf},
    CFloor={${zone.c1_gf}},
    ARoof=${zone.area_rt},
    alphaRoof=${zone.alpha_conv_inner_rt},
    nRoof=1,
    RRoof={${zone.r1_rt}},
    RRoofRem=${zone.r_rest_rt},
    CRoof={${zone.c1_rt}},
    nOrientations=${len(zone.orientation_wall)},
% if merge_windows is True:
    AWin={${list_to_string([0] * len(zone.orientation_wall))}},
% else:
    AWin={${list_to_string(zone.window_areas)}},
% endif
    ATransparent={${list_to_string(zone.window_areas)}},
% if merge_windows is True:
    AExt={${list_to_string([a + b for a, b in zip(zone.window_areas, zone.outer_walls_areas)])}})
    "Thermal zone"
% else:
    AExt={${list_to_string(zone.outer_walls_areas)}}) "Thermal zone"
% endif
    annotation (Placement(transformation(extent={{44,-2},{92,34}})));
% if merge_windows is True:
  Annex60.ThermalZones.ReducedOrder.EquivalentAirTemperature.VDI6007 eqAirTemp(
    n=${len(zone.orientation_wall)},
    wfGro=${list_to_string(zone.weightfactor_ground)},
    wfWall={${list_to_string(zone.weightfactor_ow)}},
    wfWin={${list_to_string(zone.weightfactor_win)}},
    withLongwave=true,
    aExt=${zone.solar_absorp_ow},
    alphaWallOut=${zone.alpha_conv_outer_ow},
    alphaRadWall=${zone.alpha_rad_outer_ow},
    eExt=${zone.ir_emissivity_outer_ow},
    TGro=${zone.t_ground}) "Computes equivalent air temperature"
    annotation (Placement(transformation(extent={{-24,-14},{-4,6}})));
% else:
  Annex60.ThermalZones.ReducedOrder.EquivalentAirTemperature.VDI6007WithWindow eqAirTemp(
    n=${len(zone.orientation_wall)},
    wfGro=${list_to_string(zone.weightfactor_ground)},
    wfWall={${list_to_string(zone.weightfactor_ow)}},
    wfWin={${list_to_string(zone.weightfactor_win)}},
    withLongwave=true,
    aExt=${zone.solar_absorp_ow},
    alphaWallOut=${zone.alpha_conv_outer_ow},
    alphaRadWall=${zone.alpha_rad_outer_ow},
    alphaWinOut=${zone.alpha_conv_outer_win},
    alphaRadWin=${zone.alpha_rad_outer_win},
    aWin=${zone.solar_absorp_win},
    eExt=${zone.ir_emissivity_outer_ow},
    eWin=${zone.ir_emissivity_win},
    TGro=${zone.t_ground}) "Computes equivalent air temperature"
    annotation (Placement(transformation(extent={{-24,-14},{-4,6}})));
% endif
  Modelica.Blocks.Math.Add solRad[${len(zone.orientation_wall)}]
    "Sums up solar radiation of both directions"
    annotation (Placement(transformation(extent={{-38,6},{-28,16}})));
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature prescribedTemperature
    "Prescribed temperature for exterior walls outdoor surface temperature"
    annotation (Placement(transformation(extent={{8,-6},{20,6}})));
% if merge_windows is False:
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature prescribedTemperature1
    "Prescribed temperature for windows outdoor surface temperature"
    annotation (Placement(transformation(extent={{8,14},{20,26}})));
  Modelica.Thermal.HeatTransfer.Components.Convection thermalConductorWin
    "Outdoor convective heat transfer of windows"
    annotation (Placement(transformation(extent={{38,16},{28,26}})));
% endif
  Modelica.Thermal.HeatTransfer.Components.Convection thermalConductorWall
    "Outdoor convective heat transfer of walls"
    annotation (Placement(transformation(extent={{36,6},{26,-4}})));
  Modelica.Blocks.Sources.Constant const[${len(zone.orientation_wall)}](each k=0)
    "Sets sunblind signal to zero (open)"
    annotation (Placement(transformation(extent={{-20,14},{-14,20}})));
  Annex60.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
    annotation (Placement(
    transformation(extent={{-100,-10},{-66,22}}),iconTransformation(
    extent={{-70,-12},{-50,8}})));
  Modelica.Blocks.Sources.Constant alphaWall(k=${zone.alpha_comb_outer_ow}
  *${zone.area_ow})
    "Outdoor coefficient of heat transfer for walls"
    annotation (Placement(
    transformation(
    extent={{-4,-4},{4,4}},
    rotation=90,
    origin={30,-16})));
% if merge_windows is False:
  Modelica.Blocks.Sources.Constant alphaWin(k=${zone.alpha_comb_outer_win}*${sum_list(zone.window_areas)})
    "Outdoor coefficient of heat transfer for windows"
    annotation (Placement(
    transformation(
    extent={{4,-4},{-4,4}},
    rotation=90,
    origin={32,38})));
% endif
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow personsRad
    "Radiative heat flow of persons"
    annotation (Placement(transformation(extent={{48,-42},{68,-22}})));
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow personsConv
    "Convective heat flow of persons"
    annotation (Placement(transformation(extent={{48,-62},{68,-42}})));
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow machinesConv
    "Convective heat flow of machines"
    annotation (Placement(transformation(extent={{48,-84},{68,-64}})));
  Modelica.Blocks.Sources.CombiTimeTable internalGains(
    table=[0,0,0,0; 3600,0,0,0; 7200,0,0,0; 10800,0,0,0; 14400,0,0,0; 18000,0,0,
        0; 21600,0,0,0; 25200,0,0,0; 25200,80,80,200; 28800,80,80,200; 32400,80,
        80,200; 36000,80,80,200; 39600,80,80,200; 43200,80,80,200; 46800,80,80,200;
        50400,80,80,200; 54000,80,80,200; 57600,80,80,200; 61200,80,80,200; 61200,
        0,0,0; 64800,0,0,0; 72000,0,0,0; 75600,0,0,0; 79200,0,0,0; 82800,0,0,0;
        86400,0,0,0],
    columns={2,3,4},
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic) "Table with profiles for persons (radiative and convective) and machines
    (convective)"
    annotation (Placement(transformation(extent={{6,-60},{22,-44}})));
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature prescribedTemperatureFloor
    "Prescribed temperature for floor plate outdoor surface temperature"
    annotation (Placement(transformation(
    extent={{-6,-6},{6,6}},
    rotation=90,
    origin={67,-12})));
  Modelica.Blocks.Sources.Constant TSoil(k=${zone.t_ground})
    "Outdoor surface temperature for floor plate"
    annotation (
    Placement(transformation(
    extent={{-4,-4},{4,4}},
    rotation=180,
    origin={84,-22})));

  Annex60.ThermalZones.ReducedOrder.EquivalentAirTemperature.VDI6007 eqAirTempVDI(
    aExt=${zone.solar_absorp_rt},
    eExt=${zone.ir_emissivity_outer_rt},
    wfGro=0,
    alphaWallOut=${zone.alpha_conv_outer_rt},
    alphaRadWall=${zone.alpha_rad_outer_rt},
    n=${len(zone.rooftops)},
    wfWall={${list_to_string(zone.weightfactor_rt)}},
    wfWin={${list_to_string([0] * len(zone.rooftops))}},
    TGro=285.15) "Computes equivalent air temperature for roof"
    annotation (Placement(transformation(extent={{30,34},{50,54}})));
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature prescribedTemperatureRoof
    "Prescribed temperature for roof outdoor surface temperature"
    annotation (Placement(transformation(extent={{-6,-6},{6,6}},rotation=-90,
    origin={67,44})));
  Modelica.Thermal.HeatTransfer.Components.Convection thermalConductorRoof
    "Outdoor convective heat transfer of roof"
    annotation (Placement(transformation(extent={{5,-5},{-5,5}},rotation=-90,
    origin={67,27})));
  Modelica.Blocks.Sources.Constant alphaRoof(k=${zone.alpha_comb_outer_rt}*${zone.area_rt})
    "Outdoor coefficient of heat transfer for roof"
    annotation (Placement(transformation(extent={{4,-4},{-4,4}},rotation=0,
    origin={86,27})));
  Modelica.Blocks.Sources.Constant const1[${len(zone.rooftops)}](each k=0)
    "Sets sunblind signal to zero (open)" annotation (Placement(transformation(
        extent={{3,-3},{-3,3}},
        rotation=90,
        origin={40,71})));
  Modelica.Blocks.Math.Add solRadRoof[${len(zone.rooftops)}]
    "Sums up solar radiation of both directions"
    annotation (Placement(transformation(extent={{4,76},{14,86}})));
  Annex60.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirTilRoof[${len(zone.rooftops)}](
    til={${list_to_string(deg_to_rad_list(zone.tilt_rt))}},
    % if bldg.latitude is None:
    each  lat=0.87266462599716,
    % else:
    each  lat=${deg_to_rad(bldg.latitude)},
    % endif
    azi={${list_to_string(deg_to_rad_list(get_azimut(zone.orientation_rt)))}})
    "Calculates direct solar radiation on titled surface for both directions"
    annotation (Placement(transformation(extent={{-68,74},{-48,94}})));
  Annex60.BoundaryConditions.SolarIrradiation.DiffusePerez HDifTilRoof[${len(zone.rooftops)}](
    til={${list_to_string(deg_to_rad_list(zone.tilt_rt))}},
    % if bldg.latitude is None:
    each  lat=0.87266462599716,
    % else:
    each  lat=${deg_to_rad(bldg.latitude)},
    % endif
    azi={${list_to_string(deg_to_rad_list(get_azimut(zone.orientation_rt)))}})
    "Calculates diffuse solar radiation on titled surface for both directions"
    annotation (Placement(transformation(extent={{-68,48},{-48,68}})));



equation
% if merge_windows is False:
  connect(eqAirTemp.TEqAirWin, prescribedTemperature1.T)
    annotation (Line(
    points={{-3,-0.2},{0,-0.2},{0,20},{6.8,20}},   color={0,0,127}));
% endif
  connect(eqAirTemp.TEqAir, prescribedTemperature.T)
    annotation (Line(points={{-3,-4},{4,-4},{4,0},{6.8,0}},
    color={0,0,127}));
  connect(weaDat.weaBus, weaBus)
    annotation (Line(
    points={{-78,62},{-74,62},{-74,18},{-84,18},{-84,12},{-83,12},{-83,6}},
    color={255,204,51},
    thickness=0.5), Text(
    string="%second",
    index=1,
    extent={{6,3},{6,3}}));
  connect(weaBus.TDryBul, eqAirTemp.TDryBul)
    annotation (Line(
    points={{-83,6},{-83,-2},{-38,-2},{-38,-10},{-26,-10}},
    color={255,204,51},
    thickness=0.5), Text(
    string="%first",
    index=-1,
    extent={{-6,3},{-6,3}}));
  connect(internalGains.y[1], personsRad.Q_flow)
    annotation (Line(points={{22.8,
    -52},{28,-52},{28,-32},{48,-32}}, color={0,0,127}));
  connect(internalGains.y[2], personsConv.Q_flow)
    annotation (Line(points={{22.8,-52},{36,-52},{48,-52}}, color={0,0,127}));
  connect(internalGains.y[3], machinesConv.Q_flow)
    annotation (Line(points={{22.8,
    -52},{28,-52},{28,-74},{48,-74}}, color={0,0,127}));
  connect(const.y, eqAirTemp.sunblind)
    annotation (Line(points={{-13.7,17},{-12,17},{-12,8},{-14,8},{-14,8}},
    color={0,0,127}));
  connect(HDifTil.HSkyDifTil, corGDoublePane.HSkyDifTil)
    annotation (Line(
    points={{-47,36},{-28,36},{-6,36},{-6,66},{4,66}}, color={0,0,127}));
  connect(HDirTil.H, corGDoublePane.HDirTil)
    annotation (Line(points={{-47,62},{-10,62},{-10,70},{4,70}},
    color={0,0,127}));
  connect(HDirTil.H,solRad. u1)
    annotation (Line(points={{-47,62},{-42,62},{-42,
    14},{-39,14}}, color={0,0,127}));
  connect(HDirTil.inc, corGDoublePane.inc)
    annotation (Line(points={{-47,58},{4,58},{4,58}}, color={0,0,127}));
  connect(HDifTil.H,solRad. u2)
    annotation (Line(points={{-47,30},{-44,30},{-44,
    8},{-39,8}}, color={0,0,127}));
  connect(HDifTil.HGroDifTil, corGDoublePane.HGroDifTil)
    annotation (Line(
    points={{-47,24},{-4,24},{-4,62},{4,62}}, color={0,0,127}));
  connect(solRad.y, eqAirTemp.HSol)
    annotation (Line(points={{-27.5,11},{-26,11},{-26,2},{-26,2}},
    color={0,0,127}));
  %for i, orient in enumerate(zone.orientation_wall):
    connect(weaDat.weaBus, HDifTil[${i+1}].weaBus)
    annotation (Line(
    points={{-78,62},{-74,62},{-74,30},{-68,30}},
    color={255,204,51},
    thickness=0.5));
    connect(weaDat.weaBus, HDirTil[${i+1}].weaBus)
    annotation (Line(
    points={{-78,62},{-73,62},{-68,62}},
    color={255,204,51},
    thickness=0.5));
  %endfor
  connect(personsRad.port, thermalZoneFourElements.intGainsRad)
    annotation (Line(
    points={{68,-32},{84,-32},{100,-32},{100,24},{92.2,24}},
    color={191,0,0}));
% if merge_windows is False:
  connect(thermalConductorWin.solid, thermalZoneFourElements.window)
    annotation (
     Line(points={{38,21},{40,21},{40,20},{43.8,20}}, color={191,0,0}));
  connect(prescribedTemperature1.port, thermalConductorWin.fluid)
    annotation (Line(points={{20,20},{28,20},{28,21}}, color={191,0,0}));
% endif
  connect(thermalZoneFourElements.extWall, thermalConductorWall.solid)
    annotation (Line(points={{43.8,12},{40,12},{40,1},{36,1}},
    color={191,0,0}));
  connect(thermalConductorWall.fluid, prescribedTemperature.port)
    annotation (Line(points={{26,1},{24,1},{24,0},{20,0}}, color={191,0,0}));
  connect(alphaWall.y, thermalConductorWall.Gc)
    annotation (Line(points={{30,-11.6},{30,-4},{31,-4}}, color={0,0,127}));
% if merge_windows is False:
  connect(alphaWin.y, thermalConductorWin.Gc)
    annotation (Line(points={{32,33.6},{32,26},{33,26}}, color={0,0,127}));
% endif
  connect(weaBus.TBlaSky, eqAirTemp.TBlaSky)
    annotation (Line(
    points={{-83,6},{-58,6},{-58,2},{-32,2},{-32,-4},{-26,-4}},
    color={255,204,51},
    thickness=0.5), Text(
    string="%first",
    index=-1,
    extent={{-6,3},{-6,3}}));
  connect(machinesConv.port, thermalZoneFourElements.intGainsConv)
    annotation (
    Line(points={{68,-74},{82,-74},{96,-74},{96,20},{92,20}}, color={191,
    0,0}));
  connect(personsConv.port, thermalZoneFourElements.intGainsConv)
    annotation (
    Line(points={{68,-52},{96,-52},{96,20},{92,20}}, color={191,0,0}));
  connect(corGDoublePane.solarRadWinTrans, thermalZoneFourElements.solRad)
    annotation (Line(points={{27,64},{34,64},{40,64},{40,31},{43,31}}, color={0,
    0,127}));
  connect(prescribedTemperatureFloor.port, thermalZoneFourElements.floor)
    annotation (Line(points={{67,-6},{68,-6},{68,-2}}, color={191,0,0}));
  connect(prescribedTemperatureFloor.T, TSoil.y) annotation (Line(points={{67,-19.2},
          {72.5,-19.2},{72.5,-22},{79.6,-22}}, color={0,0,127}));
  connect(prescribedTemperatureRoof.port, thermalConductorRoof.fluid)
    annotation (Line(points={{67,38},{67,38},{67,32}}, color={191,0,0}));
  connect(thermalConductorRoof.solid, thermalZoneFourElements.roof)
    annotation (Line(points={{67,22},{66.8,22},{66.8,13}}, color={191,0,0}));
  connect(thermalConductorRoof.Gc, alphaRoof.y)
    annotation (Line(points={{72,27},{78,27},{81.6,27}},color={0,0,127}));
  connect(eqAirTempVDI.TDryBul, eqAirTemp.TDryBul)
    annotation (Line(points={{28,38},{-96,38},{-96,-36},{-38,-36},{-38,-44},{
          -26,-44}},
    color={0,0,127}));
  connect(eqAirTempVDI.TBlaSky, eqAirTemp.TBlaSky)
    annotation (Line(points={{28,44},{-34,44},{-98,44},{-98,-42},{-58,-42},{-58,
          -32},{-32,-32},{-32,-38},{-26,-38}},
    color={0,0,127}));
  connect(const1.y, eqAirTempVDI.sunblind)
    annotation (Line(points={{40,67.7},{40,56}}, color={0,0,127}));
  connect(eqAirTempVDI.TEqAir, prescribedTemperatureRoof.T) annotation (Line(
        points={{51,44},{56,44},{56,58},{67,58},{67,51.2}}, color={0,0,127}));
  %for i, orient in enumerate(zone.rooftops):
    connect(weaDat.weaBus, HDifTilRoof[${i+1}].weaBus) annotation (Line(
      points={{-76,22},{-74,22},{-74,58},{-68,58}},
      color={255,204,51},
      thickness=0.5));
    connect(weaDat.weaBus, HDirTilRoof[${i+1}].weaBus) annotation (Line(
      points={{-76,22},{-74,22},{-74,84},{-68,84}},
      color={255,204,51},
      thickness=0.5));
  %endfor
  connect(HDirTilRoof.H, solRadRoof.u1)
    annotation (Line(points={{-47,84},{-22,84},{3,84}}, color={0,0,127}));
  connect(HDifTilRoof.H, solRadRoof.u2) annotation (Line(points={{-47,58},{-22,
          58},{-22,78},{3,78}}, color={0,0,127}));
  connect(eqAirTempVDI.HSol, solRadRoof.y) annotation (Line(points={{28,50},
          {6,50},{6,46},{-83,46},{-83,6}}, color={0,0,127}), Text(
      string="%second",
      index=1,
      extent={{6,3},{6,3}}));
end ${bldg.name}_${zone.name.replace(" ", "")};

##list to string
<%def name="list_to_string(list)", filter="trim">
  <%
  string_of_list = ""
  for item in list:
    string_of_list += str(item) + ", "
  string_of_list = string_of_list[:-2]
  return string_of_list
  %>
</%def>
##get azimut for modelica
<%def name="get_azimut(list)", filter="trim">
  <%
  newlist = []
  for element in list:
    if 0 < element < 360:
        newlist.append(-180.0+element)
    elif element == 0:
        newlist.append(180.0)
    elif element == -1.0:
        newlist.append(0.0)
    elif element == -2:
        newlist.append(0.0)
  return newlist

  %>
</%def>
##transform deg to rad
<%def name="deg_to_rad(value)", filter="trim">
  <%
  import math
  value_rad=value*math.pi/180
  return value_rad
  %>
</%def>

##transform deg to rad for lists
<%def name="deg_to_rad_list(list)", filter="trim">
  <%
  import math
  newlist = []
  for element in list:

    element_new=element*math.pi/180
    newlist.append(element_new)
  return newlist
  %>
</%def>

##sums entries of a list
<%def name="sum_list(list)", filter="trim">
  <%
  return sum(list)
  %>
</%def>

##returns string of list of exterior walls
<%def name="get_AExt_list(zone)", filter="trim">
  <%
  wall_list = []
  for wall in zone.outer_walls:
    wall_list.append(wall.area)
  string_list = list_to_string(wall_list)
  return string_list
  %>
</%def>

##returns mean alphaRad for indoor calculations
<%def name="mean_alphaRad(zone)", filter="trim">
  <%
  total_area = zone.area_ow + zone.area_iw + zone.area_win
  rad_mean = (zone.alpha_rad_inner_ow * zone.area_ow + zone.alpha_rad_inner_iw *
  zone.area_iw + zone.alpha_rad_inner_win * zone.area_win) / total_area
  return str(rad_mean)
  %>
</%def>
