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

  Annex60.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    calTSky=Annex60.BoundaryConditions.Types.SkyTemperatureCalculation.HorizontalRadiation,
    computeWetBulbTemperature=false,
    filNam="${weather.replace("\\", "/")}")
    "Weather data reader"
    annotation (Placement(transformation(extent={{-98,52},{-78,72}})));
  Annex60.BoundaryConditions.SolarIrradiation.DiffusePerez HDifTil[${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))}](
    each outSkyCon=true,
    each outGroCon=true,
    til={${list_to_string(deg_to_rad_list(add_gf_list(zone.tilt_wall,zone.area_gf)))}},
    each lat = ${deg_to_rad(check_lat(bldg.latitude))},
    azi={${list_to_string(deg_to_rad_list(add_gf_list(get_azimut(zone.orientation_wall),zone.area_gf)))}})
    "Calculates diffuse solar radiation on titled surface for all directions"
    annotation (Placement(transformation(extent={{-68,20},{-48,40}})));
  Annex60.BoundaryConditions.SolarIrradiation.DirectTiltedSurface HDirTil[${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))}](
    til={${list_to_string(deg_to_rad_list(add_gf_list(zone.tilt_wall,zone.area_gf)))}},
    each lat = ${deg_to_rad(check_lat(bldg.latitude))},
    azi={${list_to_string(deg_to_rad_list(add_gf_list(get_azimut(zone.orientation_wall),zone.area_gf)))}})
    "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=${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))},
  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.TwoElements
  thermalZoneTwoElements(
    redeclare package Medium = Modelica.Media.Air.DryAirNasa,
% if zone.consider_air_capacity is True:
    VAir=${zone.volume},
% else:
    VAir=0.0,
% endif
    alphaExt=${def_alpha(zone.alpha_conv_inner_ow)},
    alphaWin=${def_alpha(zone.alpha_conv_inner_win)},
    gWin=${zone.weighted_g_value},
    ratioWinConRad=${zone.windows[0].a_conv},
    nExt=1,
    RExt={${def_val(zone.r1_ow)}},
    CExt={${def_val(zone.c1_ow)}},
    alphaRad=${def_alpha(mean_alphaRad(zone))},
    AInt=${zone.area_iw},
    alphaInt=${def_alpha(zone.alpha_conv_inner_iw)},
    nInt=1,
    RInt={${def_val(zone.r1_iw)}},
    CInt={${def_val(zone.c1_iw)}},
    RWin=${def_val(zone.r1_win-R_zero(zone.alpha_comb_outer_win,zone.area_win))},
    RExtRem=${def_val(zone.r_rest_ow-R_zero(zone.alpha_comb_outer_ow,zone.area_ow))},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    extWallRC(thermCapExt(each der_T(fixed=true))),
    intWallRC(thermCapInt(each der_T(fixed=true))),
    nOrientations=${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))},
% if merge_windows is True:
    AWin={${list_to_string(add_gf_list([0] * len(zone.orientation_wall),zone.area_gf))}},
% else:
    AWin={${list_to_string(add_gf_list(zone.window_areas,zone.area_gf))}},
% endif
    ATransparent={${list_to_string(add_gf_list(zone.window_areas,zone.area_gf))}},
% if merge_windows is True:
    AExt={${list_to_string(add_gf_area([a + b for a, b in zip(zone.window_areas, zone.outer_walls_areas)],zone.area_gf))}})
    "Thermal zone"
% else:
    AExt={${list_to_string(add_gf_area(zone.outer_walls_areas,zone.area_gf))}}) "Thermal
    zone"
% endif
    annotation (Placement(transformation(extent={{44,-2},{92,34}})));
% if merge_windows is True:
  Annex60.ThermalZones.ReducedOrder.EquivalentAirTemperature.VDI6007 eqAirTemp(
    n=${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))},
    wfGro=${list_to_string(zone.weightfactor_ground)},
    wfWall={${list_to_string(add_gf_list(zone.weightfactor_ow,zone.area_gf))}},
    wfWin={${list_to_string(add_gf_list(zone.weightfactor_win,zone.area_gf))}},
    withLongwave=true,
    aExt=${zone.solar_absorp_ow},
    alphaWallOut=${def_alpha(zone.alpha_conv_outer_ow)},
    alphaRad=${def_alpha(zone.alpha_rad_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=${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))},
    wfGro=${list_to_string(zone.weightfactor_ground)},
    wfWall={${list_to_string(add_gf_list(zone.weightfactor_ow,zone.area_gf))}},
    wfWin={${list_to_string(add_gf_list(zone.weightfactor_win,zone.area_gf))}},
    withLongwave=true,
    aExt=${zone.solar_absorp_ow},
    alphaWallOut=${def_alpha(zone.alpha_conv_outer_ow)},
    alphaRad=${def_alpha(zone.alpha_rad_outer_ow)},
    alphaWinOut=${def_alpha(zone.alpha_conv_outer_win)},
    TGro=${zone.t_ground}) "Computes equivalent air temperature"
    annotation (Placement(transformation(extent={{-24,-14},{-4,6}})));
% endif
  Modelica.Blocks.Math.Add solRad[${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))}]
    "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[${def_nOrientations(add_gf(len(zone.orientation_wall),zone.area_gf))}](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=${def_alpha(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=${def_alpha(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}})));
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 in range(max(1,add_gf(len(zone.orientation_wall),zone.area_gf))):
    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, thermalZoneTwoElements.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, thermalZoneTwoElements.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(thermalZoneTwoElements.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, thermalZoneTwoElements.intGainsConv)
    annotation (
    Line(points={{68,-74},{82,-74},{96,-74},{96,20},{92,20}}, color={191,
    0,0}));
  connect(personsConv.port, thermalZoneTwoElements.intGainsConv)
    annotation (
    Line(points={{68,-52},{96,-52},{96,20},{92,20}}, color={191,0,0}));
  connect(corGDoublePane.solarRadWinTrans, thermalZoneTwoElements.solRad)
    annotation (Line(points={{27,64},{34,64},{40,64},{40,31},{43,31}}, color={0,
    0,127}));
  annotation (experiment(
  StopTime=${modelica_info.runtime_simulation},
      Interval=${modelica_info.interval_output},
      __Dymola_Algorithm="${modelica_info.current_solver}"),
      __Dymola_experimentSetupOutput(__Dymola_experimentSetupOutput(equidistant=${get_true_false(modelica_info.equidistant_output)},
      events=${get_true_false(modelica_info.results_at_events)})));
end ${bldg.name}_${zone.name};

##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>

##convert deg to rad for list
<%def name="deg_to_rad_list(list)", filter="trim">
  <%
  newlist = []
  for element in list:
    newlist.append(deg_to_rad(element))
  return newlist
  %>
</%def>

##convert deg to rad
<%def name="deg_to_rad(value)", filter="trim">
  <%
  from math import pi
  return_value = value * pi/180
  return return_value
  %>
</%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>

##checks if latitude is not None and set Aachen otherwise
<%def name="check_lat(latitude)", filter="trim">
  <%
  if latitude is None:
    return_value = 50.775466
  else:
    return_value = latitude
  return return_value
  %>
</%def>

##default values for nOrientations
<%def name="def_nOrientations(value)", filter="trim">
  <%
  if value is None or value == 0:
    return_value = 1
  else:
    return_value = value
  return return_value
  %>
</%def>

##default values for nOrientations
<%def name="def_nOrientations(value)", filter="trim">
  <%
  if value is None or value == 0:
    return_value = 1
  else:
    return_value = value
  return return_value
  %>
</%def>

##default values for alphas
<%def name="def_alpha(value)", filter="trim">
  <%
  if value is None or value == 0:
    return_value = 0.001
  else:
    return_value = value
  return return_value
  %>
</%def>

##default values for C's or R's
<%def name="def_val(value)", filter="trim">
  <%
  if not value or value <= 0:
     return_value = 0.00001
  else:
     return_value = value
  return return_value
  %>
</%def>

##Guarded calculation of resistance out of conductance and area
<%def name="R_zero(cond, area)", filter="trim">
  <%
  if cond * area != 0:
    return_value = 1/(cond*area)
  else:
    return_value = 0
  return return_value
  %>
</%def>

##Adds dummies to lists for extra orientations for ground floor
<%def name="add_gf_list(list, area_gf)", filter="trim">
  <%
  newlist=[]
  for element in list:
    newlist.append(element)
  if area_gf != 0:
    newlist.append(0)
  return newlist
  %>
</%def>

##Adds one to value for extra orientations for ground floor
<%def name="add_gf(value, area_gf)", filter="trim">
  <%
  if area_gf != 0:
    return_value = value + 1
  else:
    return_value = value
  return return_value
  %>
</%def>

##Adds ground floor area to lists
<%def name="add_gf_area(list, area_gf)", filter="trim">
  <%
  newlist=[]
  for element in list:
    newlist.append(element)
  if area_gf != 0:
    newlist.append(area_gf)
  return newlist
  %>
</%def>

##get false
<%def name="get_true_false(value)", filter="trim">
  <%
  if value == False:
    return "false"
  elif value == True:
    return "true"
  else:
    return value
  %>
</%def>