Module: BTAP::Resources::Envelope::Constructions

Defined in:
lib/openstudio-standards/btap/envelope.rb

Overview

This module contains methods dealing with the creation and modification of constructions.

Defined Under Namespace

Classes: ConstructionsTests

Class Method Summary collapse

Class Method Details

.adjust_opaque_construction(construction:, req_conductance:) ⇒ <String]OpenStudio::Model::getConstructionByName

This removes construction layers if the required conductance for a construction is higher than the maximum conductance that construction can have. Otherwise it modifies existing layers to set their thickness or resistance values (depending on what is in the layer) to achieve the required conductance.

Parameters:

  • construction (String)

    the construction we are modifying

  • req_conductance (Fixnum)

    the conductance we are trying to reach

Returns:

  • (<String]OpenStudio::Model::getConstructionByName)

    the final construction after modification

Author:



650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
# File 'lib/openstudio-standards/btap/envelope.rb', line 650

def self.adjust_opaque_construction(construction:, req_conductance:)
  layer_comp = []
  # Extract the thickness, conductivity, resistance of each layer of the construction.  If the material is
  # "No Mass", or "Air gap" set the conductivity (how well the material conducts heat) and conductance (how well
  # the material with a given thickness conducts heat) to the inverse of the resistance.  This is because
  # No Mass and Air gap materials do not have a thickness value.  Also, include which layer index the material
  # has and the material object itself.
  construction.layers.each_with_index do |layer, layer_index|
    mat_type = layer.iddObjectType.valueName.to_s
    case mat_type
    when "OS_Material"
      mat_layer = layer.to_StandardOpaqueMaterial.get
      layer_comp << {
          thickness_m: mat_layer.thickness.to_f,
          conductivity_SI: mat_layer.conductivity.to_f,
          conductance_SI: (mat_layer.conductivity.to_f / mat_layer.thickness.to_f),
          resistance_SI: (mat_layer.thickness.to_f / mat_layer.conductivity.to_f),
          construction_index: layer_index,
          layer_object: mat_layer
      }
    when "OS_Material_NoMass"
      mat_layer = layer.to_MasslessOpaqueMaterial.get
      layer_comp << {
          thickness_m: 0,
          conductivity_SI: 1.0 / mat_layer.thermalResistance.to_f,
          conductance_SI: 1.0 / mat_layer.thermalResistance.to_f,
          resistance_SI: mat_layer.thermalResistance.to_f,
          construction_index: layer_index,
          layer_object: mat_layer
      }
    when "OS_Material_AirGap"
      mat_layer = layer.to_AirGap.get
      layer_comp << {
          thickness_m: 0,
          conductivity_SI: 1.0 / mat_layer.thermalResistance.to_f,
          conductance_SI: 1.0 / mat_layer.thermalResistance.to_f,
          resistance_SI: mat_layer.thermalResistance.to_f,
          construction_index: layer_index,
          layer_object: mat_layer
      }
    end
  end
  # Sort the above layers by the conductivity of the layers.  The lowest conductivity layers first followed by
  # layers with progressively higher conductivities.
  sorted_layers = layer_comp.sort { |a, b| b[:conductivity_SI] <=> a[:conductivity_SI] }
  index = 0
  total_conductance = construction.thermalConductance.to_f
  # The following loop steps through the array of layers, sorted form highest conductivity to lowest.  It
  # deletes a layer in the construction if the conductance for the layer is not enough to reach the total
  # conductance for the construction that we are trying to reach.  If modifies the thickness or resistance
  # (depending on the layer material type) of a layer if doing so will reach the overall construction
  # conductance target. The total conductance of the construction is rounded because the conductance never seems
  # to be set precisely enough.

  while total_conductance.round(4) < req_conductance
    # There are too indicies that are tracked:
    # index:  The index of the element in the sorted array of layers that we are currently considering
    # const_index:  The index of the layer we are currently considering in the construction
    # Note that both the construction array and sorted array contain the same elements.  However these elements
    # may be in a different order.  Thus, the index and const_index may be different.  They will both indicate
    # the same layer.  However, they may differ because the sorted array is sorted by conductivity while the
    # construction array is ordered with the first layer outside (a given space) and the final layer inside (a
    # given space).
    const_index = sorted_layers[index][:construction_index]
    # Check if modifying the resistance of the currently layer will be enough to reach our total construction
    # conductance goal.  If it will, modify the layer.  If it will not, delete the layer.
    if sorted_layers[index][:resistance_SI] > ((1.0 / total_conductance) - (1.0 / req_conductance))
      # If the current layer is a NoMass or AirGap material its thickness is zero so we set the resistance.
      if sorted_layers[index][:thickness_m] == 0
        # Determine the resistance we want to set the layer to.
        res_mod = sorted_layers[index][:resistance_SI] - ((1.0 / total_conductance) - (1.0 / req_conductance))
        # Find out if the layer is an AirGap or NoMass and set the resistance for the layer with the right
        # command systax.
        mat_type = construction.layers[const_index].iddObjectType.valueName.to_s
        case mat_type
        when "OS_Material_NoMass"
          construction.layers[const_index].to_MasslessOpaqueMaterial.get.setThermalResistance(res_mod)
        when "OS_Material_AirGap"
          construction.layers[const_index].to_AirGap.get.setThermalResistance(res_mod)
        end
      else
        # The the current layer is a regular opaque material it has a thickness so we set that to reach the
        # desired resistance for that layer.
        # Determine the thickness we want to set the layer.
        thick_mod = (sorted_layers[index][:resistance_SI] - ((1.0 / total_conductance) - (1.0 / req_conductance))) * (sorted_layers[index][:conductivity_SI])
        # Set the thickness of the layer.
        construction.layers[const_index].to_StandardOpaqueMaterial.get.setThickness(thick_mod)
      end
      # Step the index of the sorted array forward by 1.  We should be able to leave the loop now because the
      # construction should have the conductance we want now.  But you never know.
      index += 1
    else
      # There the layer could not be adjusted to reach the desired conductance for the construction so get rid
      # of the layer.
      # If this is the only layer then we cannot get rid of it so throw an error.  This should never happen but
      # you never know.
      if sorted_layers.size == 1
        raise ("Could not set conductance of construction #{construction.name.to_s} to #{req_conductance} because existing layers make this impossible. Could not automatically change the constructions. Change the construction to allow for this conductance to be set.")
        return construction
      end
      # Delete the layer from the construction.
      construction.eraseLayer(const_index)
      # Delete the layer from the sorted set of layers (so that both the construction array and sorted array
      # continue to contain the same layers).
      sorted_layers.delete_at(index)
      # Go through the sorted array and change the construction indicies so that they continue to point to the
      # correct layers of the construction array. Note that index is not increased.  This is because the element
      # we were looking at just got removed so its index will be the same as that of what would have been the
      # next element.
      sorted_layers.each do |sorted_layer|
        if sorted_layer[:construction_index] > (const_index - 1)
          sorted_layer[:construction_index] -= 1
        end
      end
    end
    # Get the revised conductance for the construction now that it has been modified (by either removing or
    # modifying layers).
    total_conductance = construction.thermalConductance.to_f
    # Check if we have anything left to modify.  If yes, then keep going.  If not, then if we have done enough
    # we can stop and return the revised construction, otherwise throw an error.
    if construction.layers.size < index + 1
      if total_conductance.round(4) >= req_conductance
        return construction
      else
        raise ("Could not set conductance of construction #{construction.name.to_s} from the current conductance of #{total_conductance} to #{req_conductance} because existing layers make this impossible. Change the construction to allow for this conductance to be set.")
        return construction
      end
    end
  end
  # We have achieved our goal, return the revised construction.
  return construction
end

.create_construction(model, name, materials, insulationLayer = nil) ⇒ String

This will create construction model

Parameters:

  • model (OpenStudio::Model::Model)
  • name (String)
  • materials (Material)
  • insulationLayer (defaults to: nil)

    nil

Returns:

Author:



896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
# File 'lib/openstudio-standards/btap/envelope.rb', line 896

def self.create_construction(model, name, materials, insulationLayer = nil)
  construction = OpenStudio::Model::Construction.new(model)
  construction.setName(name)
  #check to see if they are all Fenestation or Opaque. Can't mix and match.
  is_fenestration = false
  is_opaque = false
  #check to see if materials are all the same type.
  materials.each do |material|
    is_fenestration = true unless material.to_FenestrationMaterial.empty?
    is_opaque = true unless material.to_OpaqueMaterial.empty?
  end
  raise ("Materials Passed are not valid. Either they are mixed Opaque/Fenestration or invalid materials") if (is_fenestration and is_opaque) or (not is_fenestration and not is_opaque)
  construction.setLayers(materials)
  construction.setInsulation(insulationLayer) unless nil == insulationLayer or is_fenestration
  return construction
end

.customize_fenestration_construction(model, construction, conductance = nil, solarTransmittanceatNormalIncidence = nil, visibleTransmittance = nil, at_temperature_c = 0.0) ⇒ String

This will customize fenestration construction

Parameters:

  • model (OpenStudio::Model::Model)
  • construction (String)
  • conductance (String) (defaults to: nil)

    nil

  • solarTransmittanceatNormalIncidence (Float) (defaults to: nil)

    nil

  • visibleTransmittance (Float) (defaults to: nil)

    nil

  • at_temperature_c (Float) (defaults to: 0.0)

    0.0

Returns:

  • (String)

    create_construction

Author:



922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
# File 'lib/openstudio-standards/btap/envelope.rb', line 922

def self.customize_fenestration_construction(
    model,
    construction,
    conductance = nil,
    solarTransmittanceatNormalIncidence = nil,
    visibleTransmittance = nil,
    at_temperature_c = 0.0)
  construction = OpenStudio::Model::getConstructionByName(model, construction.name.to_s).get
  raise ("This is not a fenestration!") unless construction.isFenestration
  #get equivilant values for tsol, tvis, and conductances.
  #TSol in this case is SHGC
  solarTransmittanceatNormalIncidence = self.get_shgc(model, construction) if solarTransmittanceatNormalIncidence.nil?
  visibleTransmittance = self.get_tvis(model, construction) if visibleTransmittance == nil
  conductance = self.get_conductance(construction) if conductance == nil
  frontSideSolarReflectanceatNormalIncidence = 1.0 - solarTransmittanceatNormalIncidence
  backSideSolarReflectanceatNormalIncidence = 1.0 - solarTransmittanceatNormalIncidence
  frontSideVisibleReflectanceatNormalIncidence = 0.081000
  backSideVisibleReflectanceatNormalIncidence = 0.081000
  infraredTransmittanceatNormalIncidence = 0.0
  frontSideInfraredHemisphericalEmissivity = 0.84
  backSideInfraredHemisphericalEmissivity = 0.84
  #store part of fenestation in array bins.
  glazing_array = Array.new()
  shading_material_array = Array.new()
  gas_array = Array.new()
  construction.layers.each do |material|
    glazing_array << material unless material.to_Glazing.empty?
    shading_material_array << material unless material.to_ShadingMaterial.empty?
    gas_array << material unless material.to_GasLayer.empty?
  end

  #set value of fictious glazing based on the fenestrations front and back if available
  unless glazing_array.first.to_StandardGlazing.empty?
    frontSideSolarReflectanceatNormalIncidence = glazing_array.first.to_StandardGlazing.get.frontSideSolarReflectanceatNormalIncidence
    frontSideVisibleReflectanceatNormalIncidence = glazing_array.first.to_StandardGlazing.get.frontSideVisibleReflectanceatNormalIncidence
    frontSideInfraredHemisphericalEmissivity = glazing_array.first.to_StandardGlazing.get.frontSideInfraredHemisphericalEmissivity
  end

  unless glazing_array.last.to_StandardGlazing.empty?
    backSideSolarReflectanceatNormalIncidence = glazing_array.last.to_StandardGlazing.get.backSideSolarReflectanceatNormalIncidence
    backSideVisibleReflectanceatNormalIncidence = glazing_array.last.to_StandardGlazing.get.backSideVisibleReflectanceatNormalIncidence
    backSideInfraredHemisphericalEmissivity = glazing_array.last.to_StandardGlazing.get.backSideInfraredHemisphericalEmissivity
  end
  #create fictious glazing.
  #assume a thickness of 0.10m
  thickness = 0.10
  #calculate conductivity
  conductivity = conductance * thickness
  data_name_suffix = "U=#{("%.3f" % conductivity).to_s} SHGC=#{("%.3f" % solarTransmittanceatNormalIncidence).to_s}"
  base_cons_name = construction.name.to_s
  if match = construction.name.to_s.match(/(.*)?:(.*)?/)
    base_cons_name = match.captures[0]
  end
  cons_name = "#{base_cons_name}:" + data_name_suffix
  glazing_name = "SimpleGlazing:" + data_name_suffix
  #Search to prevent the massive duplication that may ensue.
  return model.getConstructionByName(cons_name).get unless model.getConstructionByName(cons_name).empty?

  #fix for Simple glazing
  glazing_name = "SimpleGlazing:" + data_name_suffix
  glazing = nil
  if model.getSimpleGlazingByName(glazing_name).empty?
    glazing_name = "SimpleGlazing:" + data_name_suffix
    glazing = OpenStudio::Model::SimpleGlazing.new(construction.model)
    glazing.setSolarHeatGainCoefficient(solarTransmittanceatNormalIncidence)
    glazing.setUFactor(conductance)
    glazing.setThickness(0.21)
    glazing.setVisibleTransmittance(visibleTransmittance)
    glazing.setName(glazing_name)
  else
    glazing = model.getSimpleGlazingByName(glazing_name).get
  end

  #add the glazing and any shading materials to the array and create construction based on this.
  new_materials_array = Array.new()
  new_materials_array << glazing
  new_materials_array.concat(shading_material_array) unless shading_material_array.empty?
  #puts new_materials_array.size
  return self.create_construction(construction.model, cons_name, new_materials_array)
end

.customize_opaque_construction(model, construction, conductance) ⇒ <String]OpenStudio::Model::getConstructionByName

This method will create a new construction based on self and a new conductance value. It will check to see if a similar construction has already been created by this method if so it will return the existing construction. If you wish to keep some of the properties, enter the string “default” instead of a numerical value.

Parameters:

  • model (OpenStudio::Model::Model)
  • construction (String)
  • conductance (Fixnum)

Returns:

  • (<String]OpenStudio::Model::getConstructionByName)

    new_construction

Author:



595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
# File 'lib/openstudio-standards/btap/envelope.rb', line 595

def self.customize_opaque_construction(model, construction, conductance)
  #Will convert from a string identifier to an object if required.
  construction = BTAP::Common::validate_array(model, construction, "Construction").first
  #If it is Opaque
  raise ("This construction is not opaque :#{construction.name}") unless (construction.isOpaque)
  minimum_resistance = 0
  base_cons_name = construction.name.to_s
  if match = construction.name.to_s.match(/(.*)?:(.*)?/)
    base_cons_name = match.captures[0]
  end
  name_prefix = "#{base_cons_name}:U-#{conductance}"

  #Check to see if we already made one like this.
  existing_construction = OpenStudio::Model::getConstructionByName(construction.model, name_prefix)
  if not existing_construction.empty?
    # if so, return existing construction
    return existing_construction.get
  end

  #create a copy
  new_construction = self.deep_copy(model, construction)

  #Change Construction name in clone
  new_construction.setName(name_prefix)

  if conductance.kind_of?(Float)
    #re-find insulation layer
    find_and_set_insulation_layer(model, new_construction)

    #Determine how low the resistance can be set. Subtract exisiting insulation
    #Values from the total resistance to see how low we can go.
    minimum_resistance = (1 / new_construction.thermalConductance.to_f) - (1.0 / new_construction.insulation.get.thermalConductance.to_f)

    #Check if the requested resistance is smaller than the minimum
    # resistance. If so, revise the construction layers.
    if minimum_resistance > (1 / conductance)
      # Changing the insulation layer will not be enough so either start removing layers or modify them to get
      # to the required conductance.
      new_construction = adjust_opaque_construction(construction: new_construction, req_conductance: conductance.to_f)
    else
      unless new_construction.setConductance(conductance)
        raise("could not set conductance of construction #{new_construction.name.to_s}")
      end
    end
  end
  return new_construction
end

.deep_copy(model, construction) ⇒ String

This will create a deep copy of the construction

Parameters:

  • model (OpenStudio::Model::Model)
  • construction (String)

Returns:

  • (String)

    new_construction

Author:



876
877
878
879
880
881
882
883
884
885
886
887
# File 'lib/openstudio-standards/btap/envelope.rb', line 876

def self.deep_copy(model, construction)
  construction = BTAP::Common::validate_array(model, construction, "Construction").first
  new_construction = construction.clone.to_Construction.get
  #interating through layers."
  (0..new_construction.layers.length - 1).each do |layernumber|
    #cloning material"
    cloned_layer = new_construction.getLayer(layernumber).clone.to_Material.get
    #"setting material to new construction."
    new_construction.setLayer(layernumber, cloned_layer)
  end
  return new_construction
end

.find_and_set_insulation_layer(model, constructions_array) ⇒ String

This method will search through the layers and find the layer with the lowest conductance and set that as the insulation layer. Note: Concrete walls or slabs with no insulation layer but with a carper will see the carpet as the insulation layer.

Parameters:

  • model (OpenStudio::Model::Model)
  • constructions_array (BTAP::Common::validate_array)

Returns:

  • (String)

    insulating_layers

Author:



547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'lib/openstudio-standards/btap/envelope.rb', line 547

def self.find_and_set_insulation_layer(model, constructions_array)
  constructions_array = BTAP::Common::validate_array(model, constructions_array, "Construction")
  insulating_layers = Array.new()
  constructions_array.each do |construction|
    return_material = ""
    #skip if already has an insulation layer set.
    next unless construction.insulation.empty?
    #set insulation layer.
    #find insulation layer
    min_conductance = 100.0
    #loop through Layers
    construction.layers.each do |layer|
      #try casting the layer to an OpaqueMaterial.
      material = nil
      material = layer.to_OpaqueMaterial.get unless layer.to_OpaqueMaterial.empty?
      material = layer.to_FenestrationMaterial.get unless layer.to_FenestrationMaterial.empty?
      #check if the cast was successful, then find the insulation layer.
      unless nil == material

        if BTAP::Resources::Envelope::Materials::get_conductance(material) < min_conductance
          #Keep track of the highest thermal resistance value.
          min_conductance = BTAP::Resources::Envelope::Materials::get_conductance(material)
          return_material = material
          unless material.to_OpaqueMaterial.empty?
            construction.setInsulation(material)
          end
        end
      end
    end
    if construction.insulation.empty? and construction.isOpaque
      raise ("construction #{construction.name.get.to_s} insulation layer could not be set!. This occurs when a insulation layer is duplicated in the construction.")
    end

    insulating_layers << return_material
  end

  return insulating_layers
end

.get_conductance(construction, at_temperature_c = 0.0) ⇒ Double

this method will get the conductance (metric) of the construction.

Parameters:

  • construction (String)
  • at_temperature_c (Float) (defaults to: 0.0)

    0.0

Returns:

  • (Double)

    1.0

Author:



850
851
852
853
854
855
856
857
858
859
# File 'lib/openstudio-standards/btap/envelope.rb', line 850

def self.get_conductance(construction, at_temperature_c = 0.0)
  #if , by accidnet a construction base was passed...convert it to a construction object.
  construction = OpenStudio::Model::getConstructionByName(construction.model, construction.name.to_s).get unless construction.to_ConstructionBase.empty?
  total = 0.0
  construction.layers.each do |material|

    total = total + 1.0 / BTAP::Resources::Envelope::Materials::get_conductance(material, at_temperature_c)
  end
  return 1.0 / total
end

.get_rsi(construction, at_temperature_c = 0.0) ⇒ Double

this method will get the rsi (metric) of the construction.

Parameters:

  • construction (String)
  • at_temperature_c (Float) (defaults to: 0.0)

    0.0

Returns:

  • (Double)

    1.0 / self.get_conductance(construction, at_temperature_c

Author:



866
867
868
# File 'lib/openstudio-standards/btap/envelope.rb', line 866

def self.get_rsi(construction, at_temperature_c = 0.0)
  return 1.0 / self.get_conductance(construction, at_temperature_c)
end

.get_shgc(model, construction) ⇒ Float

This model gets tsol

Parameters:

  • model (OpenStudio::Model::Model)
  • construction (String)

Returns:

  • (Float)

    tsol

Author:



809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
# File 'lib/openstudio-standards/btap/envelope.rb', line 809

def self.get_shgc(model, construction)
  construction = BTAP::Common::validate_array(model, construction, "Construction").first
  construction = OpenStudio::Model::getConstructionByName(model, construction.name.to_s).get
  tsol = 1.0
  if construction.isFenestration

    construction.layers.each do |layer|
      #check to see if it is a simple glazing. If so use the SHGC method.
      tsol = tsol * layer.to_SimpleGlazing.get.solarHeatGainCoefficient unless layer.to_SimpleGlazing.empty?
      #check to see if it is a standard glazing. If so use the solar transmittance method.
      tsol = tsol * layer.to_StandardGlazing.get.solarTransmittance unless layer.to_StandardGlazing.empty?
    end
  end
  return tsol
end

.get_tvis(model, construction) ⇒ Float

This model gets tvis

Parameters:

  • model (OpenStudio::Model::Model)
  • construction (String)

Returns:

  • (Float)

    tvis

Author:



830
831
832
833
834
835
836
837
838
839
840
841
842
843
# File 'lib/openstudio-standards/btap/envelope.rb', line 830

def self.get_tvis(model, construction)
  construction = BTAP::Common::validate_array(model, construction, "Construction").first
  construction = OpenStudio::Model::getConstructionByName(model, construction.name.to_s).get
  tvis = 1.0
  if construction.isFenestration
    construction.layers.each do |layer|
      #check to see if it is a simple glazing. If so use the SHGC method.
      tvis = tvis * layer.to_SimpleGlazing.get.visibleTransmittance.get unless layer.to_SimpleGlazing.empty? || layer.to_SimpleGlazing.get.visibleTransmittance.empty?
      #check to see if it is a standard glazing. If so use the solar transmittance method.
      tvis = tvis * layer.to_StandardGlazing.get.visibleTransmittanceatNormalIncidence.get unless layer.to_StandardGlazing.empty? || layer.to_StandardGlazing.get.visibleTransmittanceatNormalIncidence.empty?
    end
  end
  return tvis
end

.should_modify_layer(mat_resistance:, total_conductance:, req_conductance:) ⇒ <Fixnum>

This checks if the construction layer can be modified to set thermal resistance of the whole construction to be less than the required resistance

Parameters:

  • mat_resistance (Fixnum)
  • total_conductance (Fixnum)
  • req_conductance (Fixnum)

Returns:

  • (<Fixnum>)

    layer resistance needed to meet construction material resistance, -999 if this is not enough

Author:



790
791
792
793
794
795
796
797
798
799
800
801
802
# File 'lib/openstudio-standards/btap/envelope.rb', line 790

def self.should_modify_layer(mat_resistance:, total_conductance:, req_conductance:)
  # Determine if the amount of resistance you can modify in this layer is greater than the amount of resistance
  # you have to change.
  if mat_resistance > ((1.0 / total_conductance) - (1.0 / req_conductance))
    # If yes, determine what the resistance for this layer should be to meet the required resistance of the
    # entire assembly.  Then return the new resistance value.
    target_res = mat_resistance - ((1.0 / total_conductance) - (1.0 / req_conductance))
    return target_res
  else
    # If no, then return an unambiguous no.
    return -999
  end
end