package Sim::OPT::Morph;
# Copyright (C) 2008-2014 by Gian Luca Brunetti and Politecnico di Milano.
# This is the module Sim::OPT::Morph of Sim::OPT, a program for detailed metadesign managing parametric explorations through the ESP-r building performance simulation platform and performing optimization by block coordinate descent.
# This is free software.  You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.

use v5.14;
use Exporter;
use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS );
use Math::Trig;
use Math::Round;
use List::Util qw[ min max reduce shuffle];
use List::MoreUtils qw(uniq);
use List::AllUtils qw(sum);
use Statistics::Basic qw(:all);
use Set::Intersection;
use List::Compare;
use IO::Tee;
use Data::Dumper;
use Sim::OPT;
use Sim::OPT::Sim;
use Sim::OPT::Retrieve;
use Sim::OPT::Report;
use Sim::OPT::Descend;
use Sim::OPT::Takechance;
#$Data::Dumper::Indent = 0;
#$Data::Dumper::Useqq  = 1;
#$Data::Dumper::Terse  = 1;
use Data::Dump qw(dump);
use feature 'say';

no strict; 
no warnings;

@ISA = qw(Exporter); # our @adamkISA = qw(Exporter);
#%EXPORT_TAGS = ( DEFAULT => [qw( &opt &prepare )]); # our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
#@EXPORT_OK   = qw(); # our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

@EXPORT = qw( 
morph translate translate_surfaces_simple translate_surfaces rotate_surface translate_vertices shift_vertices rotate 
rotatez make_generic_change reassign_construction change_thickness obs_modify bring_obstructions_back 
recalculateish daylightcalc daylightcalc_other change_config checkfile change_climate recalculatenet apply_constraints 
reshape_windows warp constrain_geometry read_geometry read_geo_constraints apply_geo_constraints vary_controls 
calc_newctl checkfile constrain_controls read_controls read_control_constraints apply_loopcontrol_changes 
apply_flowcontrol_changes constrain_obstructions read_obstructions read_obs_constraints apply_obs_constraints 
vary_net read_net apply_node_changes 
apply_component_changes constrain_net read_net_constraints propagate_constraints 
); # our @EXPORT = qw( );

$VERSION = '0.40.11'; # our $VERSION = '';



sub morph
{
	my $swap = shift; #say $tee "swapINMORPH: " . dump($swap);
	my %dat = %$swap;
	my @instances = @{ $dat{instances} }; #say "scalar(\@instances): " . scalar(@instances);
	my $countcase = $dat{countcase}; #say "dump(\$countcase): " . dump($countcase); # IT WILL BE SHADOWED. CUT ZZZ
	my $countblock = $dat{countblock}; #say "dump(\$countblock): " . dump($countblock); # IT WILL BE SHADOWED. CUT ZZZ		
	my %dirfiles = %{ $dat{dirfiles} }; #say "dump(\%dirfiles): " . dump(%dirfiles); 
		
	$configfile = $main::configfile; #say "dump(\$configfile): " . dump($configfile);
	@sweeps = @main::sweeps; #say "dump(\@sweeps): " . dump(@sweeps);
	@varinumbers = @main::varinumbers; #say "dump(\@varinumbers): " . dump(@varinumbers);
	@mediumiters = @main::mediumiters;
	@rootnames = @main::rootnames; #say "dump(\@rootnames): " . dump(@rootnames);
	%vals = %main::vals; #say "dump(\%vals): " . dump(%vals);
	
	$mypath = $main::mypath;  #say $tee "dumpINMORPH(\$mypath): " . dump($mypath);
	$exeonfiles = $main::exeonfiles; #say $tee "dumpINMORPH(\$exeonfiles): " . dump($exeonfiles);
	$generatechance = $main::generatechance; 
	$file = $main::file;
	$preventsim = $main::preventsim;
	$fileconfig = $main::fileconfig; #say $tee "dumpINMORPH(\$fileconfig): " . dump($fileconfig); # NOW GLOBAL. TO MAKE IT PRIVATE, FIX PASSING OF PARAMETERS IN CONTRAINTS PROPAGATION SECONDARY SUBROUTINES
	$outfile = $main::outfile;
	$toshell = $main::toshell;
	$report = $main::report;
	$simnetwork = $main::simnetwork;
	
	$tee = new IO::Tee(\*STDOUT, ">>$toshell"); # GLOBAL ZZZ
	
	open ( OUTFILE, ">>$outfile" ) or die "Can't open $outfile: $!"; 
	open ( TOSHELL, ">>$toshell" ) or die "Can't open $toshell: $!"; 
	say $tee "\n# Now in Sim::OPT::Morph.\n";
	
	%dowhat = %main::dowhat;

	@themereports = @main::themereports; #say "dumpINMORPH(\@themereports): " . dump(@themereports);
	@simtitles = @main::simtitles; #say "dumpINMORPH(\@simtitles): " . dump(@simtitles);
	@reporttitles = @main::reporttitles;
	@simdata = @main::simdata;
	@retrievedata = @main::retrievedata;
	@keepcolumns = @main::keepcolumns;
	@weights = @main::weights;
	@weightsaim = @main::weightsaim;
	@varthemes_report = @main::varthemes_report;
	@varthemes_variations = @vmain::arthemes_variations;
	@varthemes_steps = @main::varthemes_steps;
	@rankdata = @main::rankdata; # CUT ZZZ
	@rankcolumn = @main::rankcolumn;
	@reporttempsdata = @main::reporttempsdata;
	@reportcomfortdata = @main::reportcomfortdata;
	@reportradiationenteringdata = @main::reportradiationenteringdata;
	@report_loadsortemps = @main::report_loadsortemps;
	@files_to_filter = @main::files_to_filter;
	@filter_reports = @main::filter_reports;
	@base_columns = @main::base_columns;
	@maketabledata = @main::maketabledata;
	@filter_columns = @main::filter_columns;
	
	my @simcases = @{ $dirfiles{simcases} }; #say "dump(\@simcases): " . dump(@simcases);
	my @simstruct = @{ $dirfiles{simstruct} }; #say "dump(\@simstruct): " . dump(@simstruct);
	my @morphcases = @{ $dirfiles{morphcases} };
	my @morphstruct = @{ $dirfiles{morphstruct} };
	my @retcases = @{ $dirfiles{retcases} };
	my @retstruct = @{ $dirfiles{retstruct} };
	my @repcases = @{ $dirfiles{repcases} };
	my @repstruct = @{ $dirfiles{repstruct} };
	my @mergecases = @{ $dirfiles{mergecases} };
	my @mergestruct = @{ $dirfiles{mergestruct} };
	my @descendcases = @{ $dirfiles{descendcases} };
	my @descendstruct = @{ $dirfiles{descendstruct} };
	
	my $morphlist = $dirfiles{morphlist}; #say "dump(\$dat{morphlist}): " . dump($dat{morphlist});
	my $morphblock = $dirfiles{morphblock};
	my $simlist = $dirfiles{simlist}; #say "dump(\$simlist): " . dump($simlist);
	my $simblock = $dirfiles{simblock};
	my $retlist = $dirfiles{retlist};
	my $retblock = $dirfiles{retblock};
	my $replist = $dirfiles{replist};
	my $repblock = $dirfiles{repblock};
	my $descendlist = $dirfiles{descendlist};
	my $descendblock = $dirfiles{descendblock};
	
	#my $getpars = shift;
	#eval( $getpars );

	#if ( fileno (MORPHLIST) 
	
	$countinstance = 1;
	foreach my $instance (@instances)
	{	
		my %d = %{$instance};
		my $countcase = $d{countcase}; say $tee "#dump(\$countcase): " . dump($countcase);
		my $countblock = $d{countblock}; say $tee "#dump(\$countblock): " . dump($countblock);
		my @miditers = @{ $d{miditers} }; say $tee "#MORPH dump(\@miditers): " . dump(@miditers);
		my @winneritems = @{ $d{winneritems} }; say $tee "#dumpIN( \@winneritems) " . dump(@winneritems);
		my $countvar = $d{countvar}; say $tee "#dump(\$countvar): " . dump($countvar);
		my $countstep = $d{countstep}; say $tee "#dump(\$countstep): " . dump($countstep);						
		my $to = $d{to}; #say $tee "dump(\$to): " . dump($to);
		my $origin = $d{origin}; say $tee "#dump(\$origin): " . dump($origin);
		my @uplift = @{ $d{uplift} }; say $tee "#dump(\@uplift): " . dump(@uplift);
		#eval($getparshere);
		
		my $rootname = Sim::OPT::getrootname(\@rootnames, $countcase); say $tee "#dump(\$rootname): " . dump($rootname);
		my @blockelts = Sim::OPT::getblockelts(\@sweeps, $countcase, $countblock); say $tee "#dumpIN( \@blockelts) " . dump(@blockelts);
		my @blocks = Sim::OPT::getblocks(\@sweeps, $countcase);  say $tee "#dumpIN( \@blocks) " . dump(@blocks);
		my $toitem = Sim::OPT::getitem(\@winneritems, $countcase, $countblock); say $tee "#dump(\$toitem): " . dump($toitem);
		my $from = Sim::OPT::getline($toitem); say $tee "#dumpIN(\$from): " . dump($from);
		my %varnums = Sim::OPT::getcase(\@varinumbers, $countcase); say $tee "#dumpIN---(\%varnums): " . dump(%varnums); 
		my %mids = Sim::OPT::getcase(\@miditers, $countcase); say $tee "#dumpIN---(\%mids): " . dump(%mids); 
		#eval($getfly);
		
		my $stepsvar = Sim::OPT::getstepsvar($countvar, $countcase, \@varinumbers); #say $tee "#dump(\$stepsvar): " . dump($stepsvar); 
		my $varnumber = $countvar; #say $tee "#dump---(\$varnumber): " . dump($varnumber) . "\n\n";  # LEGACY VARIABLE
		
		my $countcaseplus1 = ( $countcase + 1);
		my $countblockplus1 = ( $countblock + 1);
		
		#@totblockelts = (@totblockelts, @blockelts); # @blockelts
		#@totblockelts = uniq(@totblockelts);
		#@totblockelts = sort(@totblockelts);
		#if ( $countvar == $#blockelts )
		#{
		#	$$general_variables[0] = "n";
		#} # THIS TELLS THAT IF THE SEARCH IS ENDING (LAST SUBSEARCH CYCLE) GENERATION OF CASES HAS TO BE TURNED OFF	
		####### OLD. $stepsvar = ${ "varnums{$countvar}" . "$varnumber" };
		
		my @applytype = @{ $vals{$countvar}{applytype} }; #say "dump(\@applytype): " . dump(@applytype);
		my $general_variables = $vals{$countvar}{general_variables}; #say "dump(\$general_variables): " . dump($general_variables);
		my @generic_change = @{$vals{$countvar}{generic_change} }; 
		my $rotate = $vals{$countvar}{rotate}; 
		my $rotatez = $vals{$countvar}{rotatez};
		my $translate = $vals{$countvar}{translate}; #say "dump(\$translate): " . dump($translate); 
		my $translate_surface_simple = $vals{$countvar}{translate_surface_simple};
		my $translate_surface = $vals{$countvar}{translate_surface};
		my $keep_obstructions = $vals{$countvar}{keep_obstructions};
		my $shift_vertices = $vals{$countvar}{shift_vertices};
		my $construction_reassignment = $vals{$countvar}{construction_reassignment};
		my $thickness_change = $vals{$countvar}{thickness_change};
		my $recalculateish = $vals{$countvar}{recalculateish};
		my @recalculatenet = @{ $vals{$countvar}{recalculatenet} };
		my $obs_modify = $vals{$countvar}{obs_modify};
		my $netcomponentchange = $vals{$countvar}{netcomponentchange};
		my $changecontrol = $vals{$countvar}{changecontrol};
		my @apply_constraints = @{ $vals{$countvar}{apply_constraints} }; # NOW SUPERSEDED BY @constrain_geometry
		my $rotate_surface = $vals{$countvar}{rotate_surface};
		my @reshape_windows = @{ $vals{$countvar}{reshape_windows} };
		my @apply_netconstraints = @{ $vals{$countvar}{apply_netconstraints} };
		my @apply_windowconstraints = @{ $vals{$countvar}{apply_windowconstraints} };
		my @translate_vertices = @{ $vals{$countvar}{translate_vertices} };
		my $warp = $vals{$countvar}{warp};
		my @daylightcalc = @{ $vals{$countvar}{daylightcalc} };
		my @change_config = @{ $vals{$countvar}{change_config} };
		my @constrain_geometry = @{ $vals{$countvar}{constrain_geometry} };
		my @vary_controls = @{ $vals{$countvar}{vary_controls} };
		my @constrain_controls =  @{ $vals{$countvar}{constrain_controls} };
		my @constrain_obstructions = @{ $vals{$countvar}{constrain_obstructions} };
		my @get_obstructions = @{ $vals{$countvar}{get_obstructions} };
		my $checkfile = $vals{$countvar}{checkfile};
		my @vary_net = @{ $vals{$countvar}{vary_net} };
		my @constrain_net = @{ $vals{$countvar}{constrain_net} };
		my @propagate_constraints = @{ $vals{$countvar}{propagate_constraints} };
		my @change_climate = @{ $vals{$countvar}{change_climate} };
		my $skip = $vals{$countvar}{skip};
		my $constrain = $vals{$countvar}{constrain};
		
		my ( @cases_to_sim, @files_to_convert );
		my ( @obs, @node, @component, @loopcontrol, @flowcontrol ); # THINGS globsAL AS REGARDS TO COUNTER ZONE CYCLES
		my ( @myobs, @mynode, @mycomponent, @myloopcontrol, @myflowcontrol); # THINGS LOCAL AS REGARDS TO COUNTER ZONE CYCLES
		my ( @tempv, @tempobs, @tempnode, @tempcomponent, @temploopcontrol, @tempflowcontrol); # THINGS LOCAL AS REGARDS TO COUNTER ZONE CYCLES
		my ( @v_, @doobs, @donode, @docomponent, @doloopcontrol, @doflowcontrol); # THINGS LOCAL AS REGARDS TO COUNTER ZONE CYCLES
		
		my $generate  = $$general_variables[0];
		my $sequencer = $$general_variables[1];
		my $dffile = "df-$file.txt";
		
		#my $toshellmorph = "$toshell" . "-1morph.txt";
		#my $outfilemorph = "$outfile" . "-1morph.txt";
		
		#open ( TOSHELL, ">>$toshellmorph" );
		#open ( OUTFILE, ">>$outfilemorph" );
						
		if ( ( $countblock == 0 ) and ( $countstep == 1 ) )
		{
			if (not ( -e "$origin" ) )
			{
				if ($exeonfiles eq "y") 
				{ 
					print `cp -R $mypath/$file $from`; #say "FROM: $from";
				}
				say TOSHELL "cp -R $mypath/$file $from\n";
			}
		}
		
		#if ( fileno (RETLIST) )
		#if (not (-e $morphlist ) )
		#{
		#	if ( $countblock == 0 )
		#	{
				open ( MORPHLIST, ">>$morphlist"); # or die;
		#	}
		#	else 
		#	{
		#		open ( MORPHLIST, ">>$morphlist"); # or die;
		#	}
		#}
		
		#if ( fileno (MORPHBLOCK) )
		#if (not (-e $morphblock ) )
		#{
		#	if ( $countblock == 0 )
		#	{
				open (MORPHBLOCK, ">>$morphblock");# or die;
		#	}
		#	else
		#	{
		#		open (MORPHBLOCK, ">>$morphblock");# or die;
		#	}		
		#}	

		push ( @{ $morphstruct[$countcase][$countblock] }, $to );
		print MORPHBLOCK "$to\n";
		if ( not ( $to ~~ @morphcases ) )
		{
			#say "HERE2. MORPHCASES.";
			push ( @morphcases, $to );
			print MORPHLIST "$to\n";
			say TOSHELL "from: $from, origin: $origin, to: $to";

			#my $from = "$case_to_sim";
			#my $almost_to = $from;
			#$almost_to =~ s/$varnumber-\d+/$varnumber-$countstep/ ;
			#if (     ( $generate eq "n" )
			#	 and ( ( $sequencer eq "y" ) or ( $sequencer eq "last" ) ) )
			#{
			#	if ( $almost_to =~ m/§$/ ) { $to = "$almost_to" ; }
			#	else
			#	{
			#		#$to = "$case_to_sim$varnumber-$countstep§";
			#		$to = "$almost_to" . "§";
			#	}
			#} 
			#elsif ( ( $generate eq "y" ) and ( $sequencer eq "n" ) )
			#{
			#	if ( $almost_to =~ m/_$/ ) { $to = "$almost_to" ; }
			#	else
			#	{
			#		$to = "$case_to_sim$varnumber-$countstep" . "_";
			#		$to = "$almost_to" . "_";
			#		if ( $countstep == $stepsvar )
			#		{
			#			if ($exeonfiles eq "y") { print `chmod -R 777 $from\n`; }
			#			print TOSHELL "chmod -R 777 $from\n\n";
			#		}
			#	}
			#} 
			#elsif ( ( $generate eq "y" ) and ( $sequencer eq "y" ) )
			#{
			#	#$to = "$case_to_sim$varnumber-$countstep" . "£";
			#	$to = "$almost_to" . "£";
			#} 
			#elsif ( ( $generate eq "y" ) and ( $sequencer eq "last" ) )
			#{
			#	if ( $almost_to =~ m/£$/ ) { $to = "$almost_to" ; }
			#	else
			#	{
			#		#$to = "$case_to_sim$varnumber-$countstep" . "£";
			#		$to = "$almost_to" . "£";
			#		#if ( $countstep == $stepsvar )
			#		#{
			#		#	if ($exeonfiles eq "y") { print `chmod -R 777 $from\n`; }
			#		#	print TOSHELL "chmod -R 777 $from\n\n";
			#		#}
			#	}
			#} 
			#elsif ( ( $generate eq "n" ) and ( $sequencer eq "n" ) )
			#{
			#	 $almost_to =~ s/[_|£]$// ;
			#	#$to = "$case_to_sim$varnumber-$countstep";
			#	$to = "$almost_to";
			#}
						
			if 
			#( 
				#( $generate eq "y" )
				#and ( $countstep == $stepsvar )
				#and ( ( $sequencer eq "n" ) or ( $sequencer eq "last" ) ) 
				#and ( ($skip ne "")  and ($skipask ne "yes") )
				#and 
				( ( not (-e $to) ) and ( not ( eval $skip) ) )
			#)
			{
				#say TOSHELL "HERE2A. MAIN. ";
			
				if ($exeonfiles eq "y") 
				{ 
					print `cp -R $origin $to\n`; 
				}
				print TOSHELL "cp -R $origin $to\n\n";
				#say "HERE2B";
				
				$countop = 0; # "$countop" IS THE COUNTER OF THE OPEATIONS
				foreach my $op (@applytype) # "$op" MEANS OPERATION
				{

					my $modification_type = $applytype[$countop][0];
					if ( ( $applytype[$countop][1] ne $applytype[$countop][2] ) and ( $modification_type ne "changeconfig" ) )
					{
						if ($exeonfiles eq "y") 
						{  
							print `cp -f $to/zones/$applytype[$countop][1] $to/zones/$applytype[$countop][2]\n`; 
						}
						print TOSHELL "cp -f $to/zones/$applytype[$countop][1] $to/zones/$applytype[$countop][2]\n\n";
						if ($exeonfiles eq "y") 
						{  
							print `cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n`; 
						}    # ORDINARILY, THIS PART CAN BE REMOVED
						print TOSHELL "cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n\n";
					}# ORDINARILY, THIS PART CAN BE REMOVED
					if ( ( $applytype[$countop][1] ne $applytype[$countop][2] ) and ( $modification_type eq "changeconfig" ) )
					{
						if ($exeonfiles eq "y") 
						{ 
							print `cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n`; 
						}
						print TOSHELL "cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n\n"; 
					} # ORDINARILY, THIS PART CAN BE REMOVED

					
					print `cd $to`;
					print TOSHELL "cd $to\n\n";
					
					if ( ( $stepsvar > 1) and ( not ( eval $skip) ) )
					{	
						sub dothings
						{	# THIS CONTAINS FUNCTIONS THAT APPLY CONSTRAINTS AND UPDATE CALCULATIONS.							
							#if ( $get_obstructions[$countop][0] eq "y" )
							#{ 
							#	get_obstructions # THIS IS TO MEMORIZE OBSTRUCTIONS.
							#	# THEY WILL BE SAVED IN A TEMPORARY FILE.
							#	($to, $fileconfig, $stepsvar, $countop, 
							#	$countstep, $exeonfiles, \@applytype, \@get_obstructions, $configfile, $countvar, $fileconfig ); 
							#}
							my ( $whatdone ) = @_;
							if ( ( $propagate_constraints[$countop] ) and ( not ( $whatdone eq "done_constraint_propagation" ) ) )
							{ 
								&propagate_constraints
								($to, $stepsvar, $countop, 
									$countstep, \@applytype, \@propagate_constraints, $countvar, $fileconfig ); 
							}
							if ( ( $constrain_geometry[$countop] ) and ( not ( $whatdone eq "done_geo_constraint" ) ) )
							{ 
								@v_ = constrain_geometry
								( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@constrain_geometry, $countvar, $fileconfig, \@v_ ); 
							}
							if ( ( $constrain_controls[$countop] ) and ( not ( $whatdone eq "done_constrol_constraint" ) ) )
							{ 
								&constrain_controls
								( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@constrain_controls, $countvar, $fileconfig ); 
							}
							if ( ( $constrain_net[$countop] ) and ( not ( $whatdone eq "done_net_constraint" ) ) )
							{ 
								&constrain_net( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@constrain_net, $to_do, $countvar, $fileconfig ); 
							}
							if ( ( $constrain_obstructions[$countop] ) and ( not ( $whatdone eq "done_obs_constraint" ) ) )
							{ 
								&constrain_obstructions
								( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@constrain_obstructions, $to_do, $countvar, $fileconfig ); 
							}
							if ( $$keep_obstructions[$countop] ) 
							{ 
								&bring_obstructions_back( $to, $stepsvar, $countop, 
									$countstep, \@applytype, $keep_obstructions, $countvar, $fileconfig ); 
							}
							if ( $apply_constraints[$countop] ) 
							{ 
								&apply_constraints
								( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@apply_constraints, $countvar, $fileconfig ); 
							}
							if ( $recalculatenet[$countop]  ) 
							{ 
								&recalculatenet
								( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@recalculatenet, $countvar, $fileconfig ); 
							}
							if ( $recalculateish eq "y" ) 
							{ 
								&recalculateish
								( $to, $stepsvar, $countop, 
									$countstep, \@applytype, \@recalculateish, $countvar, $fileconfig ); 
							}
							if ( $daylightcalc[0] eq "y" ) 
							{ 
								&daylightcalc
								( $to, $stepsvar, $countop,  
									$countstep, \@applytype, $filedf, \@daylightcalc, $countvar, $fileconfig ); 
							}
						} # END SUB DOTHINGS

						if ( $modification_type eq "generic_change" )#
						{
							&make_generic_change
							($to, $stepsvar, $countop, $countstep,
								\@applytype, $generic_change, $countvar, $fileconfig );
							&dothings;
						} #
						elsif ( $modification_type eq "surface_translation_simple" )
						{
							&translate_surfaces_simple
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $translate_surface_simple, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "surface_translation" )
						{
							&translate_surfaces 
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $translate_surface, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "surface_rotation" )              #
						{
							&rotate_surface
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $rotate_surface, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "vertices_shift" )
						{
							&shift_vertices
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $shift_vertices, $countvar, $fileconfig );
							&dothings;
						}
						elsif ( $modification_type eq "vertex_translation" )
						{
							&translate_vertices
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, \@translate_vertices, $countvar, $fileconfig );                         
							&dothings;
						}  
						elsif ( $modification_type eq "construction_reassignment" )
						{
							&reassign_construction
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $construction_reassignment, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "rotation" )
						{
							&rotate
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $rotate, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "translation" )
						{
							&translate
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $translate, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "thickness_change" )
						{
							&change_thickness
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $thickness_change, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "rotationz" )
						{
							&rotatez
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $rotatez, $countvar, $fileconfig  );
							&dothings;
						} 
						elsif ( $modification_type eq "change_config" )
						{
							&change_config
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, \@change_config, $countvar, $fileconfig );
							&dothings;
						}
						elsif ( $modification_type eq "window_reshapement" ) 
						{
							&reshape_windows
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, \@reshape_windows, $countvar, $fileconfig );					
							&dothings;
						}
						elsif ( $modification_type eq "obs_modification" )  # REWRITE FOR NEW GEO FILE?
						{
							&obs_modify
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $obs_modify, $countvar, $fileconfig );
							&dothings;
						}
						elsif ( $modification_type eq "warping" )
						{
							&warp
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, $warp, $countvar, $fileconfig );
							&dothings;
						}
						elsif ( $modification_type eq "vary_controls" )
						{
							&vary_controls
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, \@vary_controls, $countvar, $fileconfig );
							&dothings;
						}
						elsif ( $modification_type eq "vary_net" )
						{
							&vary_net
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, \@vary_net, $countvar, $fileconfig );
							&dothings;
						}
						elsif ( $modification_type eq "change_climate" )
						{
							&change_climate
							($to, $stepsvar, $countop, $countstep, 
								\@applytype, \@change_climate, $countvar, $fileconfig );
							&dothings;
						} 
						elsif ( $modification_type eq "vary_controls" )
						{
							&dothings( "done_control_constraint" );
						}
						elsif ( $modification_type eq "constrain_geometry" )
						{
							&dothings( "done_geo_constraint" );
						}
						elsif ( $modification_type eq "vary_net" )
						{
							&dothings( "done_net_constraint" );
						}
						elsif ( $modification_type eq "constrain_obstructions" )
						{
							&dothings( "done_obs_constraint" );
						}
						elsif ( $modification_type eq "propagate_constraints" )
						{
							&dothings( "done_constraint_propagation" );
						}
					}
					$countop++;
					print `cd $mypath`;
					print TOSHELL "cd $mypath\n\n";
				}
			}
			#else
			#{
			#	if ($exeonfiles eq "y") { print `cp -R $origin $to\n`; }
			#	print TOSHELL "cp -R $origin $to\n\n";
			#}
			#push(@morphed, $to);
		}
		close MORPHLIST;
		close MORPHBLOCK;
		$countinstance++;
	}
	close TOSHELL;
	close OUTFILE;
	return (\@morphcases, \@morphsruct);
}    # END SUB morph


sub translate
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $translate, $countvar, $fileconfig ) = @_;
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Translating zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	say TOSHELL "#Translating zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	if ( $stepsvar > 1 )
	{
		my $yes_or_no_translate_obstructions = "$$translate[$countop][0]";
		my $yes_or_no_update_radiation =  $$translate[$countop][1];
		my $configfile =  $$translate[$countop][3];
		if ( $yes_or_no_update_radiation eq "y" )
		{
			$yes_or_no_update_radiation = "a";
		} 
		else
		{
			$yes_or_no_update_radiation = "c";
		}

		my @coordinates_for_movement = @{ $$translate[$countop][1] };
		my $x_end = $coordinates_for_movement[0];
		my $y_end = $coordinates_for_movement[1];
		my $z_end = $coordinates_for_movement[2];
		my $x_swingtranslate = ( 2 * $x_end );
		my $y_swingtranslate = ( 2 * $y_end );
		my $z_swingtranslate = ( 2 * $z_end );
		my $x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
		my $x_movement = (- ( $x_end - ( $x_pace * ( $countstep - 1 ) ) ));
		my $y_pace = ( $y_swingtranslate / ( $stepsvar - 1 ) );
		my $y_movement = (- ( $y_end - ( $y_pace * ( $countstep - 1 ) ) ));
		my $z_pace = ( $z_swingtranslate / ( $stepsvar - 1 ) );
		my $z_movement = (- ( $z_end - ( $z_pace * ( $countstep - 1 ) ) ));

my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
i
e
$x_movement $y_movement $z_movement
y
$yes_or_no_translate_obstructions
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";

		if ($exeonfiles eq "y") 
		{ 
			print `$printthis`;
		}
		print TOSHELL 
		"#Translating zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.\"
$printthis
";
	}
}    # end sub translate

my $countcycles_transl_surfs = 0;					


sub translate_surfaces
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $translate_surface, $countvar, $fileconfig ) = @_; 
	say TOSHELL "got \$to : " . dump($to); say TOSHELL "got \$stepsvar : " . dump($stepsvar);
	say TOSHELL "got \$countop : " . dump($countop); say TOSHELL "got \$countstep : " . dump($countstep);
	say TOSHELL "got \$swap : " . dump($swap); say TOSHELL "got \$translate_surface : " . dump($translate_surface);
	say TOSHELL "got \$countvar : " . dump($countvar); say TOSHELL "got \$fileconfig : " . dump($fileconfig);
	
	my @applytype = @$swap; say TOSHELL "got \@applytype : " . dump(@applytype);
	my $zone_letter = $applytype[$countop][3]; say TOSHELL "got \$zone_letter : " . dump($zone_letter);
	
	say "Translating surfaces for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $transform_type = $$translate_surface[$countop][0]; say TOSHELL "got \$transform_type : " . dump($transform_type);
	my @surfs_to_transl = @{ $translate_surface->[$countop][1] }; say TOSHELL "got \@surfs_to_transl : " . dump(@surfs_to_transl);
	my @ends_movs = @{ $translate_surface->[$countop][2] };  say TOSHELL "got \@ends_movs : " . dump(@ends_movs);  # end points of the movements.
	my $yes_or_no_update_radiation = $$translate_surface[$countop][3]; say TOSHELL "got \$yes_or_no_update_radiation : " . dump($yes_or_no_update_radiation);
	my @transform_coordinates = @{ $translate_surface->[$countop][4] }; say TOSHELL "got \@transform_coordinates : " . dump(@transform_coordinates);
	my $countsurface = 0;
	my ( $end_mov, $mov_surf, $pace, $movement, $surface_letter_constrainedarea, $movement_constrainedarea, $pace, $swing_surf, $movement );

	foreach my $surface_letter (@surfs_to_transl)
		{ 	say TOSHELL "got \$surface_letter : " . dump($surface_letter);
			say TOSHELL "got \$stepsvar : " . dump($stepsvar);
			if ( $stepsvar > 1 )
			{
				say TOSHELL "got \$transform_type : " . dump($transform_type);
				if ($transform_type eq "a")
				{
					$end_mov = $ends_movs[$countsurface]; say TOSHELL "got \$end_mov : " . dump($end_mov);  say TOSHELL "got \$countstep : " . dump($countstep);
					if ( ref ( $end_mov ) )
					{
						my $min = $end_mov->[0]; say TOSHELL "FROM REF got \$min : " . dump($min);
						my $max = $end_mov->[1]; say TOSHELL "FROM REF got \$max : " . dump($max);
						$swing_surf = ( $max - $min ); say TOSHELL "FROM REF got \$swing_surf : " . dump($swing_surf);
						$end_mov = ( $swing_surf / 2 ); say TOSHELL "FROM REF got \$end_mov : " . dump($end_mov); 
					}
					else
					{
						$swing_surf = $end_mov * 2; say TOSHELL "got \$swing_surf : " . dump($swing_surf);
					}
					
					$pace = ( $swing_surf / ( $stepsvar - 1 ) ); say TOSHELL "got \$pace : " . dump($pace);
					say TOSHELL "got \$end_mov : " . dump($end_mov); say TOSHELL "got \$countstep : " . dump($countstep); 
					$movement = ( - ( ($end_mov) -( $pace * ( $countstep - 1 ) ) ) ); say TOSHELL "RESULT: got \$movement : " . dump($movement);
						
					my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
$transform_type
$movement
y
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}
				print TOSHELL "
#Translating surfaces for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance
$printthis";

				$countsurface++;
				$countcycles_transl_surfs++;
			}
			elsif ($transform_type eq "b")
			{
				my @coordinates_for_movement = @{ $transform_coordinates[$countsurface] };
				my $x_end = $coordinates_for_movement[0];
				my $y_end = $coordinates_for_movement[1];
				my $z_end = $coordinates_for_movement[2];
				my $x_swingtranslate = ( 2 * $x_end );
				my $y_swingtranslate = ( 2 * $y_end );
				my $z_swingtranslate = ( 2 * $z_end );
				my $x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
				my $x_movement = (- ( $x_end - ( $x_pace * ( $countstep - 1 ) ) ));
				my $y_pace = ( $y_swingtranslate / ( $stepsvar - 1 ) );
				my $y_movement = (- ( $y_end - ( $y_pace * ( $countstep - 1 ) ) ));
				my $z_pace = ( $z_swingtranslate / ( $stepsvar - 1 ) );
				my $z_movement = (- ( $z_end - ( $z_pace * ( $countstep - 1 ) ) ));

				my $printthis = 
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
$transform_type
$x_movement $y_movement $z_movement
y
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";

				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}

				print TOSHELL "
#Translating surfaces for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance
$printthis";

				$countsurface++;
				$countcycles_transl_surfs++;
			}
		}
	}						
}    # END SUB translate_surfaces


sub rotate_surface
{
	my ( $to, $stepsvar, $countop, $countstep, $applytyperef, $rotate_surface, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$applytyperef;
	my $zone_letter = $applytype[$countop][3];
	
	say "Rotating surfaces for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	
	my @surfs_to_rotate =  @{ $rotate_surface->[$countop][0] };
	my @vertices_numbers =  @{ $rotate_surface->[$countop][1] };   
	my @swingrotations = @{ $rotate_surface->[$countop][2] };
	my @yes_or_no_apply_to_others = @{ $rotate_surface->[$countop][3] };
	my $configfile = $$rotate_surface[$countop][4];
	my ( $swingrotate, $pacerotate, $rotation_degrees, $vertex_number, $yes_or_no_apply );

	my $countrotate = 0;
	foreach my $surface_letter (@surfs_to_rotate)
	{
		$swingrotate = $swingrotations[$countrotate];

		if ( ref ( $swingrotate ) )
		{
			my $min = $end_mov_>[0];
			my $max = $end_mov->[1];
			$swingrotate = ( $max - $min );
		}
		else
		{
			$swingrotate = $end_mov * 2;
		}

		$pacerotate = ( $swingrotate / ( $stepsvar - 1 ) );
		$rotation_degrees = ( ( $swingrotate / 2 ) - ( $pacerotate * ( $countstep - 1 ) )) ;
		$vertex_number = $vertices_numbers[$countrotate];
		$yes_or_no_apply = $yes_or_no_apply_to_others[$countrotate];
		if (  ( $swingrotate != 0 ) and ( $stepsvar > 1 )  and ( $yes_or_no_rotate_surfs eq "y" ) )
		{
			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
c
$vertex_number
$rotation_degrees
$yes_or_no_apply
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}

			print  TOSHELL "
Rotating surfaces for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance
$printthis";
		}
		$countrotate++;
	}
}    # END SUB rotate_surface


sub translate_vertices # TO BE RE-TESTED.
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig) = @_;
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @translate_vertices = @$swap2;
	say "Translating vertices for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	my @v;
	my @verts_to_transl = @{ $translate_vertices[$countop][0] };
	my @transform_coordinates = @{ $translate_vertices[$countop][1] };
	my @sourcefiles = @{ $translate_vertices[$countop][2] };
	my @longmenus = @{ $translate_vertices[$countop][3] };
	
	my $sourcefile = $sourcefiles[ $countops ];
	my $longmenu = $longmenus[ $countops ];
	my $sourceaddress = "$mypath/$file$sourcefile";
	
	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourcefile 2: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;
		
	my $countlines = 0;
	my $countvert = 0;

	my @vertex_letters;
	if ($longmenu eq "y")
	{
		@vertex_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
		"n", "o", "p", "0\nb\nq", "0\nb\nr", "0\nb\ns", "0\nb\nt", "0\nb\nu", "0\nb\nv", 
		"0\nb\nw", "0\nb\nx", "0\nb\ny", "0\nb\nz", "0\nb\na", "0\nb\nb","0\nb\nc","0\nb\nd",
		"0\nb\ne","0\nb\n0\nb\nf","0\nb\n0\nb\ng","0\nb\n0\nb\nh","0\nb\n0\nb\ni",
		"0\nb\n0\nb\nj","0\nb\n0\nb\nk","0\nb\n0\nb\nl","0\nb\n0\nb\nm","0\nb\n0\nb\nn",
		"0\nb\n0\nb\no","0\nb\n0\nb\np","0\nb\n0\nb\nq","0\nb\n0\nb\nr","0\nb\n0\nb\ns",
		"0\nb\n0\nb\nt");
	}
	else
	{
		@vertex_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
		"n", "o", "p", "0\nq", "0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", 
		"0\ny", "0\nz", "0\na", "0\nb","0\n0\nc","0\n0\nd","0\n0\ne","0\n0\nf","0\n0\ng",
		"0\n0\nh","0\n0\ni","0\n0\nj","0\n0\nk","0\n0\nl","0\n0\nm","0\n0\nn","0\n0\no",
		"0\n0\np","0\n0\nq","0\n0\nr","0\n0\ns","0\n0\nt");
	}

	foreach my $line (@lines)
	{
		$line =~ s/^\s+//; 
		my @rowelements = split(/\s+|,/, $line);
		if   ($rowelements[0] eq "*vertex" ) 
		{
			if ($countvert == 0) 
			{
				push (@v, [ "vertices of  $sourceaddress" ]);
				push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ], $vertexletters[$countvert] );
			}

			if ($countvert > 0) 
			{
				push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3], $vertexletters[$countvert] ] );
			}
			$countvert++;
		}
		$countlines++;
	}

	my $countvertex = 0;		
	foreach my $vertex_letter (@vertex_letters)
	{
		my ( $x_swingtranslate, $y_swingtranslate, $z_swingtranslate );
		my @base_coordinates = @{ $transform_coordinates[ $countvertex ] };
		
		my $x_end = $base_coordinates[0];
		if ( ref ( $x_end ) )
		{
			my $min = $x_end->[0];
			my $max = $x_end->[1];
			$x_swingtranslate = ( $max - $min );
		}
		else
		{
			$x_swingtranslate = ( 2 * $x_end );
		}

		my $y_end = $base_coordinates[1];
		if ( ref ( $y_end ) )
		{
			my $min = $y_end->[0];
			my $max = $y_end->[1];
			$y_swingtranslate = ( $max - $min );
		}
		else
		{
			$y_swingtranslate = ( 2 * $y_end );
		}
		
		my $z_end = $base_coordinates[2];
		if ( ref ( $z_end ) )
		{
			my $min = $z_end->[0];
			my $max = $z_end->[1];
			$z_swingtranslate = ( $max - $min );
		}
		else
		{
			$z_swingtranslate = ( 2 * $z_end );
		}
		
		my $x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
		my $x_movement = (- ( $x_end - ( $x_pace * ( $countstep - 1 ) ) ));
		my $y_pace = ( $y_swingtranslate / ( $stepsvar - 1 ) );
		my $y_movement = (- ( $y_end - ( $y_pace * ( $countstep - 1 ) ) ));
		my $z_pace = ( $z_swingtranslate / ( $stepsvar - 1 ) );
		my $z_movement = (- ( $z_end - ( $z_pace * ( $countstep - 1 ) ) ));
		my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
$vertex_letter
$x_movement $y_movement $z_movement
-
y
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";
		if ($exeonfiles eq "y") 
		{ 
			print `$printthis`;
		}

		print TOSHELL "
#Translating vertices for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.			
$printthis";
		$countvertex++;
	}
	$countops++;
} # END SUB translate_vertices


sub shift_vertices
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $shift_vertices, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Shifting vertices for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my ( $pace, $movement );
	my $movementtype = $$shift_vertices[$countop][0];
	my @pairs_of_vertices = @{ $$shift_vertices[$countop][1] };
	my @shift_swings = @{ $$shift_vertices[$countop][2] };
	my $yes_or_no_radiation_update = $$shift_vertices[$countop][3];
	my $configfile = $$shift_vertices[$countop][4];
	
	if ( $stepsvar > 1 )
	{
		my $countthis = 0;
		if ($movementtype eq "j")
		{
		foreach my $shift_swing (@shift_swings)
			{
				
				if ( ref ( $shift_swing ) )
				{
					my $min = $shift_swing->[0];
					my $max = $shift_swing->[1];
					$shift_swing = ( $max - $min );
				}
				else 
				{
					;
				}
				
				$pace = ( $shift_swing / ( $stepsvar - 1 ) );
				$movement_or_vertex = ( ( ($shift_swing) / 2 ) - ( $pace * ( $countstep - 1 ) ) );
				$vertex1 = $pairs_of_vertices[ 0 + ( 2 * $countthis ) ];
				$vertex2 = $pairs_of_vertices[ 1 + ( 2 * $countthis ) ];
				
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
^
$movementtype
$vertex1
$vertex2
-
$movement_or_vertex
y
-
y
-
y
-
-
-
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}
				print TOSHELL "
#Shifting vertices for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";

				$countthis++;
			}
		}
		elsif ($movementtype eq "h")
		{
			foreach my $shift_swing (@shift_swings)
			{
				my $printthis = 
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
^
$movementtype
$vertex1
$vertex2
-
$movement_or_vertex
-
y
n
n
n
-
y
-
y
-
-
-
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}
				print TOSHELL "
#Shifting vertices for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
			}
		}
	}
}    # END SUB shift_vertices


sub rotate    # generic zone rotation
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $rotate, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Rotating zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $rotation_degrees; 
	my $swingrotate = $$rotate[$countop][0];
	
	if ( ref ( $swingrotate ) )
	{
		my $min = $swingrotate->[0];
		my $max = $swingrotate->[1];
		$swingrotate = ( $max - $min );
	}
										
	my $yes_or_no_update_radiation = $$rotate[$countop][1];
	my $base_vertex = $$rotate[$countop][2];
	my $configfile = $$rotate[$countop][3];						  
	my $pacerotate; 
	my $count_rotate = 0;
	if ( ( $swingrotate != 0 ) and ( $stepsvar > 1 ) )
	{
		$pacerotate = ( $swingrotate / ( $stepsvar - 1 ) );
		$rotation_degrees = ( ( $swingrotate / 2 ) - ( $pacerotate * ( $countstep - 1 ) ) );

		my $printthis = 
"prj -file $to/cfg/$fileconfig -mode script<<YYY


m
c
a
$zone_letter
i
b
$rotation_degrees
$base_vertex
-
$yes_or_no_rotate_obstructions
-
y
c
-
y
-
-
-
-
-
-
-
-
YYY
";

		if ($exeonfiles eq "y") 
		{ 
			print `$printthis`;
		}
		print TOSHELL 
		"
#Rotating zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis
";
	}
}    # END SUB rotate


sub rotatez # PUT THE ROTATION POINT AT POINT 0, 0, 0. I HAVE NOT YET MADE THE FUNCTION GENERIC ENOUGH.
{	
	my ( $to, $stepsvar, $countop, $countstep, $swap, $rotatez, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Rotating zones on the vertical plane for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @centerpoints = @{$$rotatez[0]};
	my $centerpointsx = $centerpoints[0];
	my $centerpointsy = $centerpoints[1];
	my $centerpointsz = $centerpoints[2];
	my $plane_of_rotation = "$$rotatez[1]";
 	my $infile = "$to/zones/$applytype[$countop][2]";
	my $infile2 = "$to/cfg/$applytype[$countop][2]";
	my $outfilemorph = "erase";
	my $outfile2 = "$to/zones/$applytype[$countop][2]eraseobtained";
	open(INFILE,  "$infile")   or die "Can't open infile $infile: $!\n";
	open($_outfile_2, ">>$outfile2") or die "Can't open outfile2 $outfile2: $!\n";
	my @lines = <INFILE>;
	close(INFILE);
	my $countline = 0;
	my $countcases = 0;
	my @vertices;
	my $swingrotate = $$rotatez[2];
	my $alreadyrotation = $$rotatez[3];
	my $rotatexy = $$rotatez[4];
	my $swingrotatexy = $$rotatez[5];
	
	if ( ref ( $swingrotate ) )
	{
		my $min = $swingrotate->[0];
		my $max = $swingrotate->[1];
		$swingrotatexy = ( $max - $min );
	}
	else { ; }
	
	if ( ref ( $swingrotate ) )
	{
		my $min = $swingrotate->[0];
		my $max = $swingrotate->[1];
		$swingrotatexy = ( $max - $min );
	}
	else { ; }
	
	my ( $pacerotate, $linenew, $linenew2 );
	my $count_rotate = 0;
	my ( @rowprovv, @rowprovv2, @row, @row2 );
	if ( $stepsvar > 1 )
	{
		foreach my $line (@lines) 
		{#
			{
				$linenew = $line;
				$linenew =~ s/\:\s/\:/g ;
				@rowprovv = split(/\s+/, $linenew);
				$rowprovv[0] =~ s/\:\,/\:/g ;
				@row = split(/\,/, $rowprovv[0]);
				if ($row[0] eq "*vertex") 
				{ push (@vertices, [$row[1], $row[2], $row[3]] ) }
			}
			$countline = $countline +1;
		}

		foreach $vertex (@vertices)
		{
			print $_outfile_ "vanilla ${$vertex}[0], ${$vertex}[1], ${$vertex}[2]\n";
		}
		foreach $vertex (@vertices)
		{
			${$vertex}[0] = (${$vertex}[0] - $centerpointsx); 
			${$vertex}[0] = sprintf("%.5f", ${$vertex}[0]);
			${$vertex}[1] = (${$vertex}[1] - $centerpointsy); 
			${$vertex}[1] = sprintf("%.5f", ${$vertex}[1]);
			${$vertex}[2] = (${$vertex}[2] - $centerpointsz); 
			${$vertex}[2] = sprintf("%.5f", ${$vertex}[2]);
			print $_outfile_ "aftersum ${$vertex}[0], ${$vertex}[1], ${$vertex}[2]\n";
		}

		my $anglealready = deg2rad(-$alreadyrotation);
		foreach $vertex (@vertices)
		{
			my $x_new = cos($anglealready)*${$vertex}[0] - sin($anglealready)*${$vertex}[1]; 
			my $y_new = sin($anglealready)*${$vertex}[0] + cos($anglealready)*${$vertex}[1];
			${$vertex}[0] = $x_new; ${$vertex}[0] = sprintf("%.5f", ${$vertex}[0]);
			${$vertex}[1] = $y_new; ${$vertex}[1] = sprintf("%.5f", ${$vertex}[1]);
			print $_outfile_ "afterfirstrotation ${$vertex}[0], ${$vertex}[1], ${$vertex}[2]\n";
		}

		$pacerotate = ( $swingrotate / ( $stepsvar - 1) );
		$rotation_degrees = - ( ($swingrotate / 2) - ($pacerotate * ($countstep -1) ) );
		my $angle = deg2rad($rotation_degrees);
		foreach $vertex (@vertices)
		{
			my $y_new = cos($angle)*${$vertex}[1] - sin($angle)*${$vertex}[2]; 
			my $z_new = sin($angle)*${$vertex}[1] + cos($angle)*${$vertex}[2];
			${$vertex}[1] = $y_new; ${$vertex}[1] = sprintf("%.5f", ${$vertex}[1]);
			${$vertex}[2] = $z_new; ${$vertex}[2] = sprintf("%.5f", ${$vertex}[2]);
			${$vertex}[0] = sprintf("%.5f", ${$vertex}[0]);
			print $_outfile_ "aftersincos ${$vertex}[0], ${$vertex}[1], ${$vertex}[2]\n";
		}

		my $angleback = deg2rad($alreadyrotation);
		foreach $vertex (@vertices)
			{
			my $x_new = cos($angleback)*${$vertex}[0] - sin($angleback)*${$vertex}[1]; 
			my $y_new = sin($angleback)*${$vertex}[0] + cos($angleback)*${$vertex}[1];
			${$vertex}[0] = $x_new; ${$vertex}[0] = sprintf("%.5f", ${$vertex}[0]);
			${$vertex}[1] = $y_new; ${$vertex}[1] = sprintf("%.5f", ${$vertex}[1]);
			print $_outfile_ "afterrotationback ${$vertex}[0], ${$vertex}[1], ${$vertex}[2]\n";ctl type
		}

		foreach $vertex (@vertices)
		{
			${$vertex}[0] = ${$vertex}[0] + $centerpointsx; ${$vertex}[0] = sprintf("%.5f", ${$vertex}[0]);
			${$vertex}[1] = ${$vertex}[1] + $centerpointsy; ${$vertex}[1] = sprintf("%.5f", ${$vertex}[1]);
			${$vertex}[2] = ${$vertex}[2] + $centerpointsz; ${$vertex}[2] = sprintf("%.5f", ${$vertex}[2]);
			print $_outfile_ "after final substraction ${$vertex}[0], ${$vertex}[1], ${$vertex}[2]\n";
		}

		my $countwrite = -1;
		my $countwriteand1;
		foreach $line (@lines) 
		{#	

				$linenew2 = $line;
				$linenew2 =~ s/\:\s/\:/g ;
				my @rowprovv2 = split(/\s+/, $linenew2);
				$rowprovv2[0] =~ s/\:\,/\:/g ;
				@row2 = split(/\,/, $rowprovv2[0]);
				$countwriteright = ($countwrite - 5);
				$countwriteand1 = ($countwrite + 1);			
				if ($row2[0] eq "*vertex")		
				{
					if ( $countwrite == - 1) { $countwrite = 0 }	
					print $_outfile_2 
					"*vertex"."\,"."${$vertices[$countwrite]}[0]"."\,"."${$vertices[$countwrite]}[1]"."\,"."${$vertices[$countwrite]}[2]"."  #   "."$countwriteand1\n";
				}
				else 
				{
					print $_outfile_2 "$line";
				}
				if ( $countwrite > ( - 1 ) ) { $countwrite++; }
		}

		close($_outfile_);
		if ($exeonfiles eq "y") { print `chmod 777 $infile`; }
		print TOSHELL "chmod -R 777 $infile\n";
		if ($exeonfiles eq "y") { print `chmod 777 $infile2`; }
		print TOSHELL "chmod -R 777 $infile2\n";
		if ($exeonfiles eq "y") { print `rm $infile`; }
		print TOSHELL "rm $infile\n";
		if ($exeonfiles eq "y") { print `chmod 777 $outfile2`; }
		print TOSHELL "chmod 777 $outfile2\n";
		if ($exeonfiles eq "y") { print `cp $outfile2 $infile`; }
		print TOSHELL "cp $outfile2 $infile\n";
		if ($exeonfiles eq "y") { print `cp $outfile2 $infile2`; }
		print TOSHELL "cp $outfile2 $infile2\n";
	}
} # END SUB rotatez


sub reassign_construction
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $construction_reassignment, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Reassign construction solutions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @surfaces_to_reassign = @{ $construction_reassignment->[$countop][0] };
	my @constructions_to_choose = @{ $construction_reassignment->[$countop][1] };
	my $configfile = $$construction_reassignment[$countop][2];
	my $surface_letter;
	my $count = 0;
	my @reassign_constructions;

	foreach $surface_to_reassign (@surfaces_to_reassign)
	{
		$construction_to_choose =  $constructions_to_choose[$count][$countstep];
		
		my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
f
$surface_to_reassign
e
n
y
$construction_to_choose
-
-
-
-
y
y
-
-
-
-
-
-
-
-
YYY
";
		if ($exeonfiles eq "y") 
		{ 
			print `$printthis`;
		}

		print TOSHELL "
#Reassign construction solutions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
		$count++;
	}

}    # END SUB reassign_construction

					
sub change_thickness
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $thickness_change, $countvar, $fileconfig ) = @_;
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Changing thicknesses in construction layer for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @entries_to_change = @{ $$thickness_change[$countop][0] };
	my @groups_of_strata_to_change = @{ $$thickness_change[$countop][1] };
	my @groups_of_couples_of_min_max_values = @{ $$thickness_change[$countop][2] };
	my $configfile = $$thickness_change[$countop][3];
	my $thiscount = 0;
	my ( $entry_to_change, $countstrata, $stratum_to_change, $min, $max, $change_stratum, $enter_change_entry, $swing, $pace, $thickness );
	my ( @strata_to_change, @min_max_values , @change_strata, @change_entries, @change_entries_with_thicknesses );

	if ( $stepsvar > 1 )
	{
		foreach $entry_to_change (@entries_to_change)
		{
			@strata_to_change = @{ $groups_of_strata_to_change[$thiscount] };
			$countstrata = 0;
			foreach $stratum_to_change (@strata_to_change)
			{
				@min_max_values = @{ $groups_of_couples_of_min_max_values[$thiscount][$countstrata] };
				$min   = $min_max_values[0];
				$max   = $min_max_values[1];
				$swing = $max - $min;
				$pace  = ( $swing / ( $stepsvar - 1 ) );
				$thickness = $min + ( $pace * ( $countstep - 1 ) );

				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY
b
e
a
$entry_to_change
$stratum_to_change
n
$thickness
-
-
y
y
-
y
y
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}
				print TOSHELL "
#Changing thicknesses in construction layer for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
				$countstrata++;
			}
			$thiscount++;
		}
		$" = " ";
		if ($exeonfiles eq "y") { print `$enter_esp$go_to_construction_database@change_entries_with_thicknesses$exit_construction_database_and_esp`; }
		print TOSHELL "$enter_esp$go_to_construction_database@change_entries_with_thicknesses$exit_construction_database_and_esp\n";
	}
} # END sub change_thickness


sub readgeofile
{	# THIS READS A GEO FILE TO GET THE DATA OF THE REQUESTED OBSTRUCTIONS
	my $geofile = $_[0]; #say "geofile: $geofile";
	open (GEOFILE, "$geofile") or die;
	my @lines = <GEOFILE>;
	close GEOFILE;

	foreach my $line (@lines)
	{
		my @elts = split(/\s+|,/, $line); #say "elts: " . dump(@elts);
		#*obs,3.000,-1.500,6.000,0.010,1.500,3.000,0.000,1.00,left3,wall27  # block   3
		if ($elts[0] eq "\*obs")
		{
			push ( @obsdata, [ @elts ] );
		}
	}
	return ( @obsdata );
}


sub obs_modify
{
	if ( $stepsvar > 1 )
	{
		my ( $to, $stepsvar, $countop, $countstep, $swap, $obs_modify, $countvar, $fileconfig ) = @_;
		my @applytype = @$swap;
		my $zone_letter = $applytype[$countop][3];
		say "Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";		

		my @obs_letters = @{ $$obs_modify[$countop][0] };
		my $modification_type = $$obs_modify[$countop][1];
		my @values = @{ $$obs_modify[$countop][2] };
		my @base = @{ $$obs_modify[$countop][3] };
		my $configfile = $$obs_modify[$countop][4];
		my $xz_resolution = $$obs_modify[$countop][5];
		my $countobs = 0;							  
		my ( $x_end, $y_end, $z_end, $x_base, $y_base, $z_base, $end_value, $base_value, $x_swingtranslate, 
		$y_swingtranslate, $z_swingtranslate, $x_pace, $x_value, $y_pace, $y_value, $z_pace, $z_value );
		if ( ($modification_type eq "a") or ($modification_type eq "b"))
		{      							  
			$x_end = $values[0];
			if ( ref ( $x_end ) )
			{
				my $min = $x_end->[0];
				my $max = $x_end->[1];
				$x_swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$x_swingtranslate = ( 2 * $x_end ); 
			}
			$x_base = $base[0];
			
			$y_end = $values[1];
			if ( ref ( $y_end ) )
			{
				my $min = $y_end->[0];
				my $max = $y_end->[1];
				$y_swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$y_swingtranslate = ( 2 * $y_end ); 
			}
			$y_base = $base[1];
			
			$z_end = $values[2];
			if ( ref ( $z_end ) )
			{
				my $min = $z_end->[0];
				my $max = $z_end->[1];
				$z_swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$z_swingtranslate = ( 2 * $z_end ); 
			}
			$z_base = $base[2];

			$x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
			$x_value = ($x_base + ( $x_end - ( $x_pace * ( $countstep - 1 ) ) ));
			$y_pace = ( $y_swingtranslate / ( $stepsvar - 1 ) );
			$y_value = ($y_base + ( $y_end - ( $y_pace * ( $countstep - 1 ) ) ));
			$z_pace = ( $z_swingtranslate / ( $stepsvar - 1 ) );
			$z_value = ($z_base + ( $z_end - ( $z_pace * ( $countstep - 1 ) ) ));

			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$obs_letter
$modification_type
a
$x_value $y_value $z_value
-
-
c
-
c
-
-
-
-
-
-
-
-
YYY
";
			foreach my $obs_letter (@obs_letters)
			{
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}
				print TOSHELL "
#Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
				$countobs++;
				}
			}

			if ( ($modification_type eq "c") or ($modification_type eq "d"))
			{      							  
				$x_end = $values[0];
				
				if ( ref ( $x_end ) )
				{
					my $min = $x_end->[0];
					my $max = $x_end->[1];
					$x_swingtranslate = ( $max - $min );
				}
				else 
				{ 
					$x_swingtranslate = ( 2 * $x_end ); 
				}
			
				$x_base = $base[0];
				$x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
				$x_value = ($x_base + ( $x_end - ( $x_pace * ( $countstep - 1 ) ) ));

				foreach my $obs_letter (@obs_letters)
				{
					my $printthis = 
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$obs_letter
$modification_type
$x_value
-
-
c
-
c
-
-
-
-
-
-
-
-
YYY
";
					if ($exeonfiles eq "y") 
					{ 
						print `$printthis`;
					}
					print TOSHELL "
#Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
					$countobs++;
				}
			}

			if ($modification_type eq "g")
			{      							  
				foreach my $obs_letter (@obs_letters)
				{
					my $count = 0;
					foreach my $x_value (@values)
					{
						if ($count < $stepsvar)
						{
							my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$obs_letter
$modification_type
$x_value
-
-
-
-
-
-
-
-
-
-
-
-
-
-
YYY
";
							if ($exeonfiles eq "y") 
							{ 
								print `$printthis`;
							}
							print TOSHELL "
Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
						$countobs++;
						$count++;
					}
				}
			}
		}

		if ($modification_type eq "h")
		{      							  
			$x_end = $values[0];
			$x_base = $base[0];
			
			if ( ref ( $x_end ) )
			{
				my $min = $x_end->[0];
				my $max = $x_end->[1];
				$x_end = ( $max - $min );
			}
			else 
			{ 
				; 
			}
				
			$x_swingtranslate = (  $x_base - $x_end );
			$x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
			$x_value = ($x_base - ( $x_pace * ( $countstep - 1 ) ));

			foreach my $obs_letter (@obs_letters)
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$obs_letter
$modification_type
$x_value
-
-
-
-
-
-
-
-
-
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y")
				{ 
					print `$printthis`;
				}
				print TOSHELL $printthis;
				$countobs++;
			}
		}

		if ($modification_type eq "t")
		{      							  
			my $modification_type = "~";
			my $what_todo = $base[0];
			$x_end = $values[0];
			$y_end = $values[1];
			$z_end = $values[2];
			
			if ( ref ( $x_end ) )
			{
				my $min = $x_end->[0];
				my $max = $x_end->[1];
				$x_swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$x_swingtranslate = ( 2 * $x_end );; 
			}
			
			if ( ref ( $y_end ) )
			{
				my $min = $y_end->[0];
				my $max = $y_end->[1];
				$y_swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$y_swingtranslate = ( 2 * $y_end );; 
			}
			
			if ( ref ( $z_end ) )
			{
				my $min = $z_end->[0];
				my $max = $z_end->[1];
				$z_swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$z_swingtranslate = ( 2 * $z_end );; 
			}
			
			$x_pace = ( $x_swingtranslate / ( $stepsvar - 1 ) );
			$x_value = ( $x_end - ( $x_pace * ( $countstep - 1 ) ) );
			$y_pace = ( $y_swingtranslate / ( $stepsvar - 1 ) );
			$y_value = ( $y_end - ( $y_pace * ( $countstep - 1 ) ) );
			$z_pace = ( $z_swingtranslate / ( $stepsvar - 1 ) );
			$z_value = ( $z_end - ( $z_pace * ( $countstep - 1 ) ) );

			foreach my $obs_letter (@obs_letters)
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$modification_type
$what_todo
$obs_letter
-
$x_value $y_value $z_value
-
c
-
c
-
-
-
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}
				print TOSHELL "
Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
				$countobs++;
				}
			}

			#NOW THE XZ GRID RESOLUTION WILL BE PUT TO THE SPECIFIED VALUE				 						
			my $printthis = #THIS IS WHAT HAPPEN INSIDE SUB KEEP_SOME_OBSTRUCTIONS
"prj -file $to/cfg/$fileconfig -mode script<<YYY


m
c
a
$zone_letter
h
a
a
$xz_resolution
-
c
-
c
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}
			print TOSHELL "
Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
	}
}    # END SUB obs_modify.


sub bring_obstructions_back
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $keep_obstructions, $countvar, $fileconfig ) = @_;
	my @applytype = @$swap;
	my $geofile = $applytype[$countop][1];
	my $zone_letter = $applytype[$countop][3];
	my $ref = $$keep_obstructions[$countop];
	my %keepobs = %$ref;
	my $what = $keepobs{what};
	my $tempname = $keepobs{tempname};
	my $obsnumbersref = $keepobs{obsnumbers};
	my @obsnumbers = @$obsnumbersref;
	
	say "Keeping some obstructions in positions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	if ( $what eq "read" )
	{
		`cp -f $geofile $tempname`;
	}
	
	if ( $what eq "write" )
	{
		open (GEOFILE, "$geofile") or die;
		my @geolines = <GEOFILE>;
		close GEOFILE;
		`mv -f $geofile $geofile.tmp `;
		
		open (TEMPFILE, "$tempname");
		my @templines = <TEMPFILE>;
		close TEMPFILE;
		
		my ( @tempobs );

		foreach my $line (@templines)
		{
			my @elts = split(/\s+|,/, $line); #say "elts: " . dump(@elts);
			#*obs,3.000,-1.500,6.000,0.010,1.500,3.000,0.000,1.00,left3,wall27  # block   3
			if ( ( $elts[0] eq "\*obs" ) and ( $elts[13] ~~ @obsnumbers ) )
			{
				push ( @tempobs, $line );
			}
		}
		
		open ( GEOFILE, ">$geofile" ) or die;
		my $countline = 0;
		foreach my $line ( @geolines )
		{
			my @elts = split(/\s+|,/, $line); #say "elts: " . dump(@elts);
			
			if ( ( $elts[0] eq "\*obs" ) and ( $elts[13] ~~ @obsnumbers ) )
			{
				print GEOFILE $templines[ $countline ];
			}
			else
			{
				print GEOFILE $line;
			}
			$countline++,
		}
		close GEOFILE;
	}
}    # END SUB bring_obstructions_back


sub recalculateish
{ 
	my ( $to, $stepsvar, $countop, $countstep, $swap, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	
	say "Updating the insolation calculations for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $zone_letter = $applytype[$countop][3];

	my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
f
*
a
a
-
-
-
-
-
-
YYY
";
	if ($exeonfiles eq "y") 
	{ 
		print `$printthis`;
	}

	print TOSHELL "
#Updating the insolation calculations for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
} #END SUB RECALCULATEISH
				

sub ifempty 
{
    my ( $dir, $d ) = @_;
    opendir($d, $dir) or die;
    return ( scalar( grep{ $_ ne "." and $_ ne ".." } readdir($d)) == 0 );
}

										
sub daylightcalc # IT WORKS ONLY IF THE "RAD" DIRECTORY IS EMPTY
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $filedf, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @daylightcalc = @$swap2;
	
	say "Performing daylight calculations through Radiance for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $zone = $daylightcalc[0];
	my $surface = $daylightcalc[1];
	my $where = $daylightcalc[2];
	my $edge = $daylightcalc[3];
	my $distance = $daylightcalc[4];
	my $density = $daylightcalc[5];
	my $accuracy = $daylightcalc[6];
	my $filedf = $daylightcalc[7];
	my $pathdf = "$to/rad/$filedf";
	my $printthis;
	
	if ( not ( ifempty ( "$to/rad/" ) ) )
	{
		$printthis =
"
cd $to/cfg/
e2r -file $to/cfg/$fileconfig -mode script<<YYY
a

d

g
-
e
d



y
-
g
y
$zone
-
$surface
$distance
$where
$edge
-
$density

i
$accuracy
y
a
a
-
-
YYY
\n\n
cd $mypath
";	
	}
	
	if ( ifempty ( "$to/rad/" ) )
	{
		$printthis =
"
cd $to/cfg/
e2r -file $to/cfg/$fileconfig -mode script<<YYY

a

a
d
$zone
-
$surface
$distance
$where
$edge
-
$density
y
$accuracy
a
-
-
-
-
-
YYY
\n\n
cd $mypath
";
	}
	
	if ($exeonfiles eq "y") 
	{ 
		print `$printthis`;
	}

	print TOSHELL "
#Performing daylight calculations through Radiance for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";

	open( RADFILE, $pathdf) or die "Can't open $pathdf: $!\n";
	my @linesrad = <RADFILE>;
	close RADFILE;											
	my @dfs;
	my $dfaverage;
	my $sum = 0;
	foreach my $linerad (@linesrad)
	{
		$linerad =~ s/^\s+//; 
		my @rowelements = split(/\s+|,/, $linerad);
		push (@dfs, $rowelements[-1]);
	}
	foreach my $df (@dfs)
	{
		$sum = ($sum + $df);
	}
	$dfaverage = ( $sum / scalar(@dfs) );

	open( DFFILE,  ">>$dffile" )   or die "Can't open $dffile: $!";
	print DFFILE "$dfaverage\n";
	close DFFILE;

} # END SUB daylightcalc 


	
sub change_config
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @change_config = @$swap2;
	
	say "Substituting a configuration file for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @change_conf = @{$change_config[$countezone]};
	my @original_configfiles = @{$change_conf[0]};
	my @new_configfiles = @{$change_conf[1]};
	my $countconfig = 0;
	my $original_configfile = $original_configfiles[$countstep-1];
	my $new_configfile = $new_configfiles[$countstep-1];
	if (  $new_configfile ne $original_configfile )
	{
		if ($exeonfiles eq "y") { print `cp -f $to/$new_configfile $to/$original_configfile\n`; }
		print TOSHELL "cp -f $to/$new_configfile $to/$original_configfile\n";
	}
$countconfig++;
} # END SUB copy_config


sub checkfile # THIS CHECKS IF A SOURCE FILE MUST BE SUBSTITUTED BY ANOTHER ONE.
{	
	my ( $sourceaddress, $targetaddress ) = @_;

	unless ( ($sourceaddress eq "" ) or ( $targetaddress eq "" ))
	{
		print $_outfile_ "TARGETFILE IN FUNCTION: $targetaddress\n";
		if ( $sourceaddress ne $targetaddress )
		{
			if ($exeonfiles eq "y") 
			{ 
				print 
				`cp -f $sourceaddress $targetaddress\n`; 
			}
			print TOSHELL 
			"cp -f $sourceaddress $targetaddress\n\n";
		}
	}
} # END SUB checkfile	


sub change_climate ### THIS SIMPLE SCRIPT HAS TO BE DEBUGGED. WHY DOES IT BLOCK ITSELF IF PRINTED TO THE SHELL?
{	# THIS FUNCTION CHANGES THE CLIMATE FILES. 
	my $to = shift;
	my $stepsvar = shift; 
	my $countop = shift;
	my $countstep = shift;
	my $swap = shift;
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my $change_climate = shift;
	my $countvar = shift;
	my $fileconfig = shift;
	
	say "Substituting climate database for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @climates = @{$change_climate[$countop]};
	my $climate = $climates[$countstep-1];
	open ( FILECONFIG, $fileconfig ) or die;
	print TOSHELL "opening $fileconfig for reading\n";
	my @lines = <FILECONFIG>;
	my ( $oldfile, $climatefolder );
	foreach my $line ( @lines )
	{
		if ( $line =~ /^\*clm/ )
		{
			my @row = split ( /\s+/ , $line );
			$climatefile = $row[1]
		}
		( $climatefolder, $oldfile ) = /(.+\/)(\w+)/ ;
		$line =~ s/$oldfile$/$climate/;
		
		my $tempfileconfig = $fileconfig . ".temp";
		open ( TEMPFILECONFIG, ">$tempfileconfig" ) or die;
		print TOSHELL "opening $tempfileconfig for printing\n";
		print TEMPFILECONFIG $line;
	}
	close FILECONFIG;
	close TEMPFILECONFIG;
	`cp -R -f $tempfileconfig $fileconfig\n`;
	print TOSHELL "cp -R -f $tempfileconfig $fileconfig\n";

	print TOSHELL "
#Substituting a configuration file with climate updated for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
}	

	
sub recalculatenet # THIS FUNCTION HAS BEEN OUTDATED BY THOSE FOR CONSTRAINING THE NETS, BELOW, BUT WORKS AND IS SIMPLER
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @recalculatenet = @$swap2;
	
	say "Adequating the ventilation network for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	
	my $filenet = $recalculatenet[0];
	my $infilenet = "$mypath/$file/nets/$filenet";
	my @nodezone_data_tot = @{$recalculatenet[1]}; ################
	my @nodesdata_tot = @{$recalculatenet[2]}; ###############
	my $geosourcefilesref = $recalculatenet[3]; ###################
	my $configaddress = $recalculatenet[4]; # FILE FOR PROPAGATION OF CONSTRAINTS
	my $y_or_n_reassign_cp = $recalculatenet[5];
	my $y_or_n_detect_obs = $recalculatenet[6];
	my @crackwidths = @{$recalculatenet[8]};
	
	my @geosourcefiles = @$geosourcefilesref; ##################
	
	my ( @geos, @genobs, @genobspoints );
	
	my $countgeo = 0;
	foreach my $nodezone_dataref ( @nodezone_data_tot )
	{
		
		my ( @obstaclesdata, @differences, @ratios );
		my $countlines = 0;
		my $countnode = 0;
		my $geosourcefile = $geosourcefiles->[ $countgeo ];
		my $sourceaddress = "$to$geosourcefile";
		open( SOURCEFILE, $sourceaddress ) or die "Can't open $geosourcefile 2: $!\n";
		my @linesgeo = <SOURCEFILE>;
		close SOURCEFILE;
		my $countvert = 0;
		my $countobs = 0;
		my ( $zone, $line, $xlenght, $ylenght, $truedistance, $heightdifference );
		my ( @rowelements, @node, @component, @v, @obs, @obspoints, @obstructionpoint );
		
		foreach my $line (@linesgeo)
		{
			$line =~ s/^\s+//; 

			my @rowelements = split(/\s+|,/, $line);
			if   ($rowelements[0] eq "*vertex" ) 
			{
				if ($countvert == 0) 
				{
					push (@v, [ "vertices_of_$sourceaddress" ]);
					push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
				}

				if ($countvert > 0) 
				{
					push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
				}
				$countvert++;
			}
			elsif   ($rowelements[0] eq "*obs" ) 
			{
				push (@obs, [ $rowelements[1], $rowelements[2], $rowelements[3], $rowelements[4], 
				$rowelements[5], $rowelements[6], $rowelements[7], $rowelements[8], $rowelements[9], $rowelements[10] ] );
				$countobs++;
			}
			$countlines++;
		}

		#if ( $y_or_n_detect_obs eq "y") ### THIS HAS YET TO BE DONE AND WORK.
		#{
		#	foreach my $ob (@obs)
		#	{
		#		push (@obspoints , [ $$ob[0], $$ob[1],$$ob[5] ] );
		#		push (@obspoints , [ ($$ob[0] + ( $$ob[3] / 2) ), ( $$ob[1] + ( $$ob[4] / 2 ) ) , $$ob[5] ] );
		#		push (@obspoints , [ ($$ob[0] + $$ob[3]), ( $$ob[1] + $$ob[4] ) , $$ob[5] ] );
		#	}
		#}
		#else 
		#{ 
			@obspoints = @{$recalculatenet[7]}; 
		#}
		push ( @geos, [ @v ] );
		push ( @genobs, [ @obs ] );
		push ( @genobspoints, [ @genobs ] );
		$countgeo++;
	}
	
	my ( @winpoints, @windowpoints, @windimsfront, @windimseast, @windimsback, @windimswest, @windsims, @windareas, @jointlenghts );
	my ( $jointfront, $jointeast, $jointback, $jointwest, $windimxfront, $windimyfront, 
		$windimxback, $windimyback, $windimxeast, $windimyeast, $windimxwest, $windimywest );

	if ($constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
	# FOR PROPAGATION OF CONSTRAINTS

	if ($y_or_n_reassign_cp == "y")
	{										
		eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS 
		# IS EVALUATED, AND HERE BELOW CONSTRAINTS ARE PROPAGATED. 
		# vertices CAN BE CALLED BY NAME with $geo[ $zonenumber ][ ]
		#  x, y or z CAN BE CALLED WITH THE NUMBERS 0, 1 or 2: EXAMPLE: $genobs[ $zonenumber ][ $vertexnumber ][ 0, 1 or 2 ]
		# ZONENUMBER DERIVES FROM $countop.
		# OBSTRUCTION CAN BE CALLED WITH $genobs[ $zonenumber ][ $obstruction_number ]
		# REMEMBER TO ASSIGN THE $height IN THE CONFIGURATION FILE. 
		# UNLESS, ESP-r WILL ASSIGN THAT FOR YOU AND THIS IS NOT ALWAYS WHAT YOU WANT.
	}


	open( INFILENET, $infilenet ) or die "Can't open $infilenet 2: $!\n";
	my @linesnet = <INFILENET>;
	close INFILENET;

	my @letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", 
	"t", "u", "v", "w", "x", "y", "z");
	
	my $countnode = 0;
	my ( $interfaceletter, $calcpressurecoefficient, $nodetype, $nodeletter, $mode );
	my $countlines = 0;
	my $countopening = 0;
	my $countcrack = 0;
	my $countthing = 0;
	my $countjoint = 0;
	foreach my $line (@linesnet)
	{
		$line =~ s/^\s+//;
		@rowelements = split(/\s+/, $line);

		if ($rowelements[0] eq "Node") { $mode = "nodemode"; }
		if ($rowelements[0] eq "Component") { $mode = "componentmode"; }
		if ( ( $mode eq "nodemode" ) and ($countlines > 1) and ($countlines < (2 + scalar(@nodesdata) ) ) )
		{
			$countnode = ($countlines - 2); 
			$zone = $nodesdata[$countnode][0];
			$interfaceletter = $nodesdata[$countnode][1];
			$calcpressurecoefficient = $nodesdata[$countnode][2];
			$nodetype = $rowelements[2];
			$nodeletter = $letters[$countnode];

			if ( $nodetype eq "0")
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY


m
e
c

n
c
$nodeletter

a
a
y
$zone

$height
a

-
-
y

y
-
-
-
-
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{ 
					print `$printthis`;
				}

				print TOSHELL "
#Adequating the ventilation network for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
				$countnode++;
			}
			elsif ( $nodetype eq "3")							
			{	
				if ($y_or_n_reassign_cp == "y")
				{
					my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY


m
e
c

n
c
$nodeletter

a
e
$zone
$interfaceletter
$calcpressurecoefficient
y

$height
-
-
y

y
-
-
-
-
-
-
-
-
YYY
";
					if ($exeonfiles eq "y") 
					{ 
						print `printthis`;
					}

					print TOSHELL "
#Adequating the ventilation network for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
					$countnode++;
				}
			}
		}

		my @node_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", 
		"q", "r", "s", "t", "u", "v", "w", "x", "y", "z");
		if ( ($mode eq "componentmode") and ( $line =~ "opening"))
		{
			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY


m
e
c

n
d
$node_letters[$countthing]

k
-
$windareas[$countopening]
-
-
y

y
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}

			print TOSHELL "
#Adequating the ventilation network for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";

			$countopening++;
			$countthing++;
		}
		elsif ( ($mode eq "componentmode") and ( $line =~ "crack "))
		{
			MY $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY


m
e
c

n
d
$node_letters[$countthing]

l
-
$crackwidths[$countjoint] $jointlenghts[$countjoint]
-
-
y

y
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}

			print TOSHELL $printthis;

			$countcrack++;
			$countthing++;
			$countjoint++;
		}
		$countlines++;
	}
} # END SUB recalculatenet



sub apply_constraints
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @apply_constraints = @$swap2;

	my ( $value_reshape, $ybasewall, $ybasewindow );
	my @v;
	
	say "Propagating geometry constraints for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	foreach my $group_operations ( @apply_constraints )
	{
		my @group = @{$group_operations};

		my @sourcefiles = @{$group[0]};
		my @targetfiles = @{$group[1]};
		my @configfiles = @{$group[2]};
		my @basevalues = @{$group[3]};
		my @swingvalues = @{$group[4]}; 
		my @work_values = @{$group[5]}; 
		my $longmenu =  $group[6]; 
		my ( $basevalue, $targetfile, $configfile, $swingvalue, $sourceaddress, $targetaddress, $configaddress );
		my $countops = 0;

		foreach $sourcefile ( @sourcefiles )
		{ 
			$basevalue = $basevalues[$countops];
			$sourcefile = $sourcefiles[$countops];
			$targetfile = $targetfiles[$countops];
			$configfile = $configfiles[$countops];
			$swingvalue = $swingvalues[$countops];
			$sourceaddress = "$to$sourcefile";
			$targetaddress = "$to$targetfile";
			$configaddress = "$to/opts/$configfile";
			$longmenu = $longmenus[$countops];
			checkfile($sourceaddress, $targetaddress);
			
			if ( ref ( $swingvalue ) )
			{
				my $min = $swingvalue->[0];
				my $max = $swingvalue->[1];
				$swingvalue = ( $max - $min );
			}
			else 
			{ 
				; 
			}
			

			open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourcefile 2: $!\n";
			my @lines = <SOURCEFILE>;
			close SOURCEFILE;
			my $countlines = 0;
			my $countvert = 0;
			foreach my $line (@lines)
			{
				$line =~ s/^\s+//; 
				my @rowelements = split(/\s+|,/, $line);
				if   ($rowelements[0] eq "*vertex" ) 
				{
					if ($countvert == 0) 
					{
						push (@v, [ "vertices of  $sourceaddress" ]);
						push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
					}

					if ($countvert > 0) 
					{
						push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
					}
					$countvert++;
				}
				$countlines++;
			}

			my @vertexletters;
			if ($longmenu eq "y")
			{
				@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
				"o", "p", "0\nb\nq", "0\nb\nr", "0\nb\ns", "0\nb\nt", "0\nb\nu", "0\nb\nv", "0\nb\nw", 
				"0\nb\nx", "0\nb\ny", "0\nb\nz", "0\nb\na", "0\nb\nb","0\nb\nc","0\nb\nd","0\nb\ne",
				"0\nb\n0\nb\nf","0\nb\n0\nb\ng","0\nb\n0\nb\nh","0\nb\n0\nb\ni","0\nb\n0\nb\nj",
				"0\nb\n0\nb\nk","0\nb\n0\nb\nl","0\nb\n0\nb\nm","0\nb\n0\nb\nn","0\nb\n0\nb\no",
				"0\nb\n0\nb\np","0\nb\n0\nb\nq","0\nb\n0\nb\nr","0\nb\n0\nb\ns","0\nb\n0\nb\nt");
			}
			else
			{
				@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
				"n", "o", "p", "0\nq", "0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", 
				"0\ny", "0\nz", "0\na", "0\nb","0\n0\nc","0\n0\nd","0\n0\ne","0\n0\nf","0\n0\ng",
				"0\n0\nh","0\n0\ni","0\n0\nj","0\n0\nk","0\n0\nl","0\n0\nm","0\n0\nn","0\n0\no",
				"0\n0\np","0\n0\nq","0\n0\nr","0\n0\ns","0\n0\nt");
			}

			if ($constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
			# FOR PROPAGATION OF CONSTRAINTS

			if (-e $configaddress) 
			{	
				eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS 
				# IS EVALUATED, AND HERE BELOW CONSTRAINTS ARE PROPAGATED.

				if ($constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
				# FOR PROPAGATION OF CONSTRAINTS


				my $countvertex = 0;
				foreach (@v)
				{
					if ($countvertex > 0)
					{			
						my $vertexletter = $vertexletters[$countvertex-1];
						if ($vertexletter ~~ @work_values)
						{
							my $printthis = 
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
$vertexletter
$v[$countvertex][0] $v[$countvertex][1] $v[$countvertex][2]
-
y
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";
							if ($exeonfiles eq "y") 
							{ 
								print `$printthis`;
							}

							print TOSHELL "
#Propagating geometry constraints for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
						}
					}
					$countvertex++;
				}
			}
			$countops++;
		}
	}
} # END SUB apply_constraints



sub reshape_windows # IT APPLIES CONSTRAINTS
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @reshape_windows = @$swap2;
	
	say "Reshaping windows for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my ( @work_letters, @v );						

	foreach my $group_operations ( @{$reshape_windows[$countop]} )
	{
		my @group = @{$group_operations};
		my @sourcefiles = @{$group[0]};
		my @targetfiles = @{$group[1]};
		my @configfiles = @{$group[2]};
		my @basevalues = @{$group[3]};
		my @swingvalues = @{$group[4]};
		my @work_letters = @{$group[5]}; 
		my @longmenus = @{$group[6]}; 

		my $countops = 0;
		foreach $sourcefile ( @sourcefiles )
		{ 
			my $basevalue = $basevalues[$countops];
			my $sourcefile = $sourcefiles[$countops];
			my $targetfile = $targetfiles[$countops];
			my $configfile = $configfiles[$countops];
			my $swingvalue = $swingvalues[$countops];
			my $longmenu = $longmenus[$countops];
			my $sourceaddress = "$to$sourcefile";
			my $targetaddress = "$to$targetfile";
			my $configaddress = "$to/opts/$configfile";
			my $totalswing;
			unless ( ref ( $swingvalue ) )
			{
				$totalswing = ( 2 * $swingvalue );
			}
			
			if ( ref ( $swingvalue ) )
			{
				my $min = $swingvalue->[0];
				my $max = $swingvalue->[1];
				$totalswing = ( $max - $min );
			}
					
			my $pace = ( $totalswing / ( $stepsvar - 1 ) );
			checkfile($sourceaddress, $targetaddress);
			
			open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourcefile 2: $!\n";
			my @lines = <SOURCEFILE>;
			close SOURCEFILE;

			my $countlines = 0;
			my $countvert = 0;
			foreach my $line (@lines)
			{
				$line =~ s/^\s+//; 

				my @rowelements = split(/\s+|,/, $line);
				if   ($rowelements[0] eq "*vertex" ) 
				{
					if ($countvert == 0) 
					{
						push (@v, [ "vertices of  $sourceaddress", [], [] ]);
						push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
					}

					if ($countvert > 0) 
					{
						push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
					}

					$countvert++;
				}
				$countlines++;
			}

			my @vertexletters;
			if ($longmenu eq "y")
			{																
				@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
				"n", "o", "p", "0\nb\nq", "0\nb\nr", "0\nb\ns", "0\nb\nt", "0\nb\nu", "0\nb\nv", 
				"0\nb\nw", "0\nb\nx", "0\nb\ny", "0\nb\nz", "0\nb\na", "0\nb\nb","0\nb\nc","0\nb\nd",
				"0\nb\ne","0\nb\n0\nb\nf","0\nb\n0\nb\ng","0\nb\n0\nb\nh","0\nb\n0\nb\ni",
				"0\nb\n0\nb\nj","0\nb\n0\nb\nk","0\nb\n0\nb\nl","0\nb\n0\nb\nm","0\nb\n0\nb\nn",
				"0\nb\n0\nb\no","0\nb\n0\nb\np","0\nb\n0\nb\nq","0\nb\n0\nb\nr","0\nb\n0\nb\ns",
				"0\nb\n0\nb\nt");
			}
			else
			{
				@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
				"n", "o", "p", "0\nq", "0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", 
				"0\ny", "0\nz", "0\na", "0\nb","0\n0\nc","0\n0\nd","0\n0\ne","0\n0\nf","0\n0\ng",
				"0\n0\nh","0\n0\ni","0\n0\nj","0\n0\nk","0\n0\nl","0\n0\nm","0\n0\nn","0\n0\no",
				"0\n0\np","0\n0\nq","0\n0\nr","0\n0\ns","0\n0\nt");
			}

			$value_reshape_window =  ( ( $basevalue - $swingvalue) + ( $pace * ( $countstep - 1 )) );

			if (-e $configaddress)
			{				

				eval `cat $configaddress`;	# HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS 
				# IS EVALUATED, AND HERE BELOW CONSTRAINTS ARE PROPAGATED.

				if (-e $constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
				# FOR PROPAGATION OF CONSTRAINTS					

				my $countvertex = 0;

				foreach (@v)
				{
					if ($countvertex > 0)
					{
						my $vertexletter = $vertexletters[$countvertex];
						if ($vertexletter  ~~ @work_letters)
						{
							my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
$vertexletter
$v[$countvertex+1][0] $v[$countvertex+1][1] $v[$countvertex+1][2]
-
y
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";
							if ($exeonfiles eq "y") 
							{ 
								print `$printthis`;
							}

							print TOSHELL "
#Reshaping windows for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
						}
					}
					$countvertex++;
				}
			}
			$countops++;
		}

	}
} # END SUB reshape_windows


sub warp #
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $warp, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say "Warping zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @surfs_to_warp =  @{ $warp->[$countop][0] };
	my @vertices_numbers =  @{ $warp->[$countop][1] };   
	my @swingrotations = @{ $warp->[$countop][2] };
	my @yes_or_no_apply_to_others = @{ $warp->[$countop][3] };
	my $configfilename = $$warp[$countop][4];
	my $configfile = $to."/opts/".$configfilename;
	my @pairs_of_vertices = @{ $warp->[$countop][5] }; # @pairs_of_vertices defining axes
	my @windows_to_reallign = @{ $warp->[$countop][6] };
	my $sourcefilename = $$warp[$countop][7];
	my $sourcefile = $to.$sourcefilename;
	my $longmenu = $$warp[$countop][8];
	my $countrotate = 0;
	foreach my $surface_letter (@surfs_to_warp)
	{
		$swingrotate = $swingrotations[$countrotate];
		
		if ( ref ( $swingrotate ) )
		{
			my $min = $swingrotate->[0];
			my $max = $swingrotate->[1];
			$swingrotate = ( $max - $min );
		}
		
		$pacerotate = ( $swingrotate / ( $stepsvar - 1 ) );
		$rotation_degrees = ( ( $swingrotate / 2 ) - ( $pacerotate * ( $countstep - 1 ) )) ;
		$vertex_number = $vertices_numbers[$countrotate];
		$yes_or_no_apply = $yes_or_no_apply_to_others[$countrotate];
		if (  ( $swingrotate != 0 ) and ( $stepsvar > 1 ) and ( $yes_or_no_warp eq "y" ) )
		{
			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
c
$vertex_number
$rotation_degrees
$yes_or_no_apply
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}
			print  TOSHELL "
#Warping zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
		}
		$countrotate++;
	}

	# THIS SECTION READS THE CONFIG FILE FOR DIMENSIONS
	open( SOURCEFILE, $sourcefile ) or die "Can't open $sourcefile: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;
	my $countlines = 0;
	my $countvert = 0;
	foreach my $line (@lines)
	{
		$line =~ s/^\s+//; 
			
		my @rowelements = split(/\s+|,/, $line);
		if   ($rowelements[0] eq "*vertex" ) 
		{
			if ($countvert == 0) 
			{
				push (@v, [ "vertices of  $sourceaddress" ]);
				push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
			}

			if ($countvert > 0) 
			{
				push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
			}
			$countvert++;
		}
		$countlines++;
	}


	my @vertexletters;
		if ($longmenu eq "y")
		{
			@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
			"o", "p", "0\nb\nq", "0\nb\nr", "0\nb\ns", "0\nb\nt", "0\nb\nu", "0\nb\nv", "0\nb\nw", 
			"0\nb\nx", "0\nb\ny", "0\nb\nz", "0\nb\na", "0\nb\nb","0\nb\nc","0\nb\nd","0\nb\ne",
			"0\nb\n0\nb\nf","0\nb\n0\nb\ng","0\nb\n0\nb\nh","0\nb\n0\nb\ni","0\nb\n0\nb\nj",
			"0\nb\n0\nb\nk","0\nb\n0\nb\nl","0\nb\n0\nb\nm","0\nb\n0\nb\nn","0\nb\n0\nb\no",
			"0\nb\n0\nb\np","0\nb\n0\nb\nq","0\nb\n0\nb\nr","0\nb\n0\nb\ns","0\nb\n0\nb\nt");
		}
		else
		{
			@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
			"o", "p", "0\nq", "0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", "0\ny", 
			"0\nz", "0\na", "0\nb","0\n0\nc","0\n0\nd","0\n0\ne","0\n0\nf","0\n0\ng","0\n0\nh",
			"0\n0\ni","0\n0\nj","0\n0\nk","0\n0\nl","0\n0\nm","0\n0\nn","0\n0\no","0\n0\np",
			"0\n0\nq","0\n0\nr","0\n0\ns","0\n0\nt");
		}


	if (-e $configfile)
	{				
		eval `cat $configfile`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED 
		# AND PROPAGATED.

		if (-e $constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
		# FOR PROPAGATION OF CONSTRAINTS

	}
	# THIS SECTION SHIFTS THE VERTEX TO LET THE BASE SURFACE AREA UNCHANGED AFTER THE WARPING.

	my $countthis = 0;
	$number_of_moves = ( (scalar(@pairs_of_vertices)) /2 ) ;
	foreach my $pair_of_vertices (@pairs_of_vertices)
	{
		if ($countthis < $number_of_moves)
		{
			$vertex1 = $pairs_of_vertices[ 0 + ( 2 * $countthis ) ];
			$vertex2 = $pairs_of_vertices[ 1 + ( 2 * $countthis ) ];

			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
^
j
$vertex1
$vertex2
-
$addedlength
y
-
y
-
y
-
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}
			print TOSHELL "
#Warping zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
		}
		$countthis++;
	}
}    # END SUB warp


##############################################################################
# BEGINNING OF THE SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING GEOMETRY
sub constrain_geometry # IT APPLIES CONSTRAINTS TO ZONE GEOMETRY
{
	# IT CONSTRAINS GEOMETRY FILES. IT HAS TO BE CALLED FROM THE MAIN FILE WITH:
	# constrain_geometry($to, $fileconfig, $stepsvar, $countop, $countstep, $exeonfiles, \@applytype, \@constrain_geometry);
	# constrain_geometry($to, $fileconfig, $stepsvar, $countop, 
	# $countstep, $exeonfiles, \@applytype, \@constrain_geometry, $to_do);
	my ( $to, $stepsvar, $countop, $countstep, $applytyperef, $constrain_geometryref, $to_do, $countvar, $fileconfig, $v_ref ) = @_;
	
	my @applytype = @$applytyperef;
	my $zone_letter = $applytype[$countop][3];
	my @constrain_geometry = @$constrain_geometryref;
	my @v_ = @$v_ref;
	
	say "Propagating constraints on geometry for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	foreach my $elm (@constrain_geometry)
	{
		my @group = @{$elm};
		my $sourcefile = $group[0];
		my $targetfile = $group[1];
		my $configfile = $group[2];
		my @work_letters = @{$group[3]}; 
		my $longmenus = $group[4]; 
		my @swings__ = @{ $group[5] };
		my $askop = $group[6]; 
		unless ( $askop ) { $askop = 0; }
		
		my $sourceaddress = "$to$sourcefile";
		my $targetaddress = "$to$targetfile";
		my $configaddress = "$to$configfile";
		
		my ( @v, @vertexletters, @work_items, @swings, @paces );
		
		foreach ( @swings__ )
		{
			if ( ref ( $_ ) )
			{
				$_ = ( $_->[0] - $_->[1] );
			}
			else
			{
				$_ = ( $_ * 2 );
			}
			push ( @swings, $_ );
		}
		
		foreach ( @swings )
		{
			my $pace = ( $_ / ( $stepsvar - 1 ) );
			push ( @paces, $pace );
		}

		if ($longmenu eq "y")
		{																
			@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
			"o", "p", "0\nb\nq", "0\nb\nr", "0\nb\ns", "0\nb\nt", "0\nb\nu", "0\nb\nv", "0\nb\nw", 
			"0\nb\nx", "0\nb\ny", "0\nb\nz", "0\nb\na", "0\nb\nb","0\nb\nc","0\nb\nd","0\nb\ne",
			"0\nb\n0\nb\nf","0\nb\n0\nb\ng","0\nb\n0\nb\nh","0\nb\n0\nb\ni","0\nb\n0\nb\nj",
			"0\nb\n0\nb\nk","0\nb\n0\nb\nl","0\nb\n0\nb\nm","0\nb\n0\nb\nn","0\nb\n0\nb\no",
			"0\nb\n0\nb\np","0\nb\n0\nb\nq","0\nb\n0\nb\nr","0\nb\n0\nb\ns","0\nb\n0\nb\nt");
		}
		else
		{
			@vertexletters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
			"n", "o", "p", "0\nq", "0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", 
			"0\ny", "0\nz", "0\na", "0\nb","0\n0\nc","0\n0\nd","0\n0\ne","0\n0\nf","0\n0\ng",
			"0\n0\nh","0\n0\ni","0\n0\nj","0\n0\nk","0\n0\nl","0\n0\nm","0\n0\nn","0\n0\no",
			"0\n0\np","0\n0\nq","0\n0\nr","0\n0\ns","0\n0\nt");
		}
		
		unless ($to_do eq "justwrite")
		{
			checkfile($sourceaddress, $targetaddress);
			@v = read_geometry( $sourceaddress );
			@v_ = read_geo_constraints( $to, $fileconfig, $stepsvar, $countop, $countstep, $configaddress, \@v, $countvar, \@swings, \@paces, \@v_ );
		}

		unless ($to_do eq "justread")
		{
			apply_geo_constraints( \@v_, \@vertexletters, \@work_letters, $exeonfiles, $zone_letter, $askop );
		} # print $_outfile_ "\@v: " . Dumper(@v) . "\n\n";
	}
} # END SUB constrain_geometry


sub read_geometry # THIS READS GEOMETRY FILES TO GET THE VERTICES.
{
	my ( $sourceaddress ) = @_;
			
	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourcefile 2: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;

	my $countlines = 0;
	my $countvert = 0;
	foreach my $line (@lines)
	{
		$line =~ s/^\s+//; 

		my @rowelements = split(/\s+|,/, $line);
		if   ($rowelements[0] eq "*vertex" ) 
		{
			push (@v, [ $rowelements[1], $rowelements[2], $rowelements[3] ] );
			$countvert++;
		}
		$countlines++;
	}
	return( @v );
} # END SUB read_geometry


sub read_geo_constraints # THIS READ GEOMETRY CONSTRAINTS.
{	
	# THIS MAKES THE vertices IN THE GEOMETRY FILES AVAILABLE TO THE USER FOR MANIPULATION, IN THE FOLLOWING FORM:
	# $v_[$countop][$number][$x], $v_[$countop][$number][$y], $v_[$countop][$number][$z]. 
	# EXAMPLE: $v_[0][4][$x] = 1. OR: @v_[0][4][$x] = @v_[0][4][$y]. OR: @v_[1][4][$x] = @v_[0][3][$z].
	# $countops number mutations in series. The $countop that is actuated is always the last, the one which is active.
	# So it is more safe to read everything that may be needed before giving instruction to activate propagation of constraints.
	# PROPAGATION OF CONSTRAINTS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO THE SPECIED VARIABLES. 
	# THE FOLLOWING VARIABLES ARE ALSO ALWAYS AVAILABLE: 
	# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
	# $countop, WHICH TELLS THE PROGRAM WHAT OPERATION IS BEING EXECUTED IN THE CHAIN OF OPERATIONS 
	# $countstep, WHICH TELLS THE PROGRAM WHAT THE CURRENT ITERATION STEP IS.
	# $countvar, WHICH TELLS THE PROGRAM WHAT NUMBER OF DESIGN PARAMETER THE PROGRAM IS WORKING AT.
	my ( $to, $fileconfig, $stepsvar, $countop, $countstep, $configaddress, $vref, $countvar, $swingsref, $pacesref, $v_ref ) = @_;
	
	my @myv = @$vref;
	my @swings = @$swingsref;
	my @paces = @$pacesref;
	my @v_ = @v_ref;

	my $x = 0;
	my $y = 1;
	my $z = 2;
	unshift (@myv, [ "vertices of  $sourceaddress. \$countop: $countop ", [], [] ]);

	if (-e $configaddress)
	{	
		push ( @v_, [ @myv ]); #
		eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED.

		if ( -e $constrain ) { eval ( $constrain ); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
		# FOR PROPAGATION OF CONSTRAINTS
		shift ( @{ $v_[$countop]} ); #
	}
	return ( @v_ );
} # END SUB read_geo_constraints


sub apply_geo_constraints
{
	my ( $v_ref, $vertexlettersref, $work_lettersref, $exeonfiles, $zone_letter, $askop ) = @_;
	
	my @v_ = @$v_ref;
	my @vertexletters = @$vertexlettersref;
	my @work_letters = @$work_lettersref;
	my @v = @{ $v_[ $askop ] };

	my $countvertex = 0;
	foreach my $v (@v)
	{
		my $vertexletter = $vertexletters[$countvertex];
		
		if ( (@work_letters eq "") or ($vertexletter  ~~ @work_letters) )
		{ 
			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
d
$vertexletter
$v[$countvertex+1][0] $v[$countvertex+1][1] $v[$countvertex+1][2]
-
y
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{
				print `$printthis`;
			}

			print TOSHELL $printthis;
		}
		$countvertex++;
	}

} # END SUB apply_geo_constraints
# END OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING GEOMETRY
##############################################################################


##############################################################################
# BEGINNING OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING CONTROLS
sub vary_controls
{  	# IT IS CALLED FROM THE MAIN FILE
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @vary_controls = @$swap2;
	
	say "Propagating constraints on controls for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my ( $semaphore_zone, $semaphore_dataloop, $semaphore_massflow, $semaphore_setpoint, $doline );
	my $count_controlmass = -1;
	my $countline = 0;
	my @letters = ("e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "z"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	my @period_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	my $loop_hour = 2; # NOTE: THE FOLLOWING VARIABLE NAMES ARE SHADOWED IN THE FOREACH LOOP BELOW, 
	# BUT ARE THE ONES USED IN THE OPT CONSTRAINTS FILES.
	my $max_heating_power = 3;
	my $min_heating_power = 4;
	my $max_cooling_power = 5,
	my $min_cooling_power = 6;
	my $heating_setpoint = 7;
	my $cooling_setpoint = 8;
	my $flow_hour = 2;
	my $flow_setpoint = 3;
	my $flow_onoff = 4;
	my $flow_fraction = 5;
	my $loop_letter;
	my $loopcontrol_letter;

	my @group = @{$vary_controls[$countop]};
	my $sourcefile = $group[0];
	my $targetfile = $group[1];
	my $configfile = $group[2];
	my @buildbulk = @{$group[3]};
	my @flowbulk = @{$group[4]};
	
	my $countbuild = 0;
	my $countflow = 0;

	my $countcontrol = 0;
	my $sourceaddress = "$to$sourcefile";
	my $targetaddress = "$to$targetfile";
	my $configaddress = "$to$configfile";	

	#@loopcontrol; # DON'T PUT "my" HERE.
	#@flowcontrol; # DON'T PUT "my" HERE.
	#@new_loopcontrols; # DON'T PUT "my" HERE.
	#@new_flowcontrols; # DON'T PUT "my" HERE.
	my ( @groupzone_letters, @zone_period_letters, @flow_letters, @fileloopbulk, @fileflowbulk );

	checkfile($sourceaddress, $targetaddress);

	if ($countstep == 1)
	{
		read_controls($sourceaddress, $targetaddress, \@letters, \@period_letters);
	}


	sub calc_newctl
	{	# TO BE CALLED WITH: calc_newcontrols($to, $fileconfig, $stepsvar, $countop, $countstep, \@buildbulk, \@flowbulk, \@loopcontrol, \@flowcontrol);
		# THIS COMPUTES CHANGES TO BE MADE TO CONTROLS BEFORE PROPAGATION OF CONSTRAINTS
		my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $swap3, $swap4, $countvar, $fileconfig ) = @_;
		
		my @buildbulk = @$swap;
		my @flowbulk = @$swap2;
		my @loopcontrol = @$swap3;
		my @flowcontrol = @$swap4;

		my ( @new_loop_hours, @new_max_heating_powers, @new_min_heating_powers, @new_max_cooling_powers, @new_min_cooling_powers, @new_heating_setpoints,
			@new_cooling_setpoints, @new_flow_hours, @new_flow_setpoints, @new_flow_onoffs, @new_flow_fractions );

		# HERE THE MODIFICATIONS TO BE EXECUTED ON EACH PARAMETERS ARE CALCULATED.
		if ($stepsvar == 0) {$stepsvar = 1;}
		if ($stepsvar > 1) 
		{
			foreach $each_buildbulk (@buildbulk)
			{
				my @askloop = @{$each_buildbulk};
				my $new_loop_letter = $askloop[0];
				my $new_loopcontrol_letter = $askloop[1];
				my $swing_loop_hour = $askloop[2];
				my $swing_max_heating_power = $askloop[3];
				my $swing_min_heating_power = $askloop[4];
				my $swing_max_cooling_power = $askloop[5];
				my $swing_min_cooling_power = $askloop[6];
				my $swing_heating_setpoint = $askloop[7];
				my $swing_cooling_setpoint = $askloop[8];

				my $countloop = 0; #IT IS FOR THE FOLLOWING FOREACH. LEAVE IT ATTACHED TO IT.
				foreach $each_loop (@loopcontrol) # THIS DISTRIBUTES THIS NESTED DATA STRUCTURES IN A FLAT MODE TO PAIR THE INPUT FILE, USER DEFINED ONE.
				{
					my $countcontrol = 0;
					@thisloop = @{$each_loop};
					# my $letterfile = $letters[$countloop];
					foreach $lp (@thisloop)
					{
						my @control = @{$lp};
						# my $letterfilecontrol = $period_letters[$countcontrol];
						$loop_letter = $loopcontrol[$countloop][$countcontrol][0];
						$loopcontrol_letter = $loopcontrol[$countloop][$countcontrol][1];
						if ( ( $new_loop_letter eq $loop_letter ) and ($new_loopcontrol_letter eq $loopcontrol_letter ) )
						{
							# print $_outfile_ "YES!: \n\n\n";
							$loop_hour__ = $loopcontrol[$countloop][$countcontrol][$loop_hour];
							$max_heating_power__ = $loopcontrol[$countloop][$countcontrol][$max_heating_power];
							$min_heating_power__ = $loopcontrol[$countloop][$countcontrol][$min_heating_power];
							$max_cooling_power__ = $loopcontrol[$countloop][$countcontrol][$max_cooling_power];
							$min_cooling_power__ = $loopcontrol[$countloop][$countcontrol][$min_cooling_power];
							$heating_setpoint__ = $loopcontrol[$countloop][$countcontrol][$heating_setpoint];
							$cooling_setpoint__ = $loopcontrol[$countloop][$countcontrol][$cooling_setpoint];
						}
						$countcontrol++;
					}
					$countloop++;
				}

				my $pace_loop_hour =  ( $swing_loop_hour / ($stepsvar - 1) );
				my $floorvalue_loop_hour = ($loop_hour__ - ($swing_loop_hour / 2) );
				my $new_loop_hour = $floorvalue_loop_hour + ($countstep * $pace_loop_hour);

				my $pace_max_heating_power =  ( $swing_max_heating_power / ($stepsvar - 1) );
				my $floorvalue_max_heating_power = ($max_heating_power__ - ($swing_max_heating_power / 2) );
				my $new_max_heating_power = $floorvalue_max_heating_power + ($countstep * $pace_max_heating_power);

				my $pace_min_heating_power =  ( $swing_min_heating_power / ($stepsvar - 1) );
				my $floorvalue_min_heating_power = ($min_heating_power__ - ($swing_min_heating_power / 2) );
				my $new_min_heating_power = $floorvalue_min_heating_power + ($countstep * $pace_min_heating_power);

				my $pace_max_cooling_power =  ( $swing_max_cooling_power / ($stepsvar - 1) );
				my $floorvalue_max_cooling_power = ($max_cooling_power__ - ($swing_max_cooling_power / 2) );
				my $new_max_cooling_power = $floorvalue_max_cooling_power + ($countstep * $pace_max_cooling_power);

				my $pace_min_cooling_power =  ( $swing_min_cooling_power / ($stepsvar - 1) );
				my $floorvalue_min_cooling_power = ($min_cooling_power__ - ($swing_min_cooling_power / 2) );
				my $new_min_cooling_power = $floorvalue_min_cooling_power + ($countstep * $pace_min_cooling_power);

				my $pace_heating_setpoint =  ( $swing_heating_setpoint / ($stepsvar - 1) );
				my $floorvalue_heating_setpoint = ($heating_setpoint__ - ($swing_heating_setpoint / 2) );
				my $new_heating_setpoint = $floorvalue_heating_setpoint + ($countstep * $pace_heating_setpoint);

				my $pace_cooling_setpoint =  ( $swing_cooling_setpoint / ($stepsvar - 1) );
				my $floorvalue_cooling_setpoint = ($cooling_setpoint__ - ($swing_cooling_setpoint / 2) );
				my $new_cooling_setpoint = $floorvalue_cooling_setpoint + ($countstep * $pace_cooling_setpoint);

				$new_loop_hour = sprintf("%.2f", $new_loop_hour);
				$new_max_heating_power = sprintf("%.2f", $new_max_heating_power);
				$new_min_heating_power = sprintf("%.2f", $new_min_heating_power);
				$new_max_cooling_power = sprintf("%.2f", $new_max_cooling_power);
				$new_min_cooling_power = sprintf("%.2f", $new_min_cooling_power);
				$new_heating_setpoint = sprintf("%.2f", $new_heating_setpoint);
				$new_cooling_setpoint = sprintf("%.2f", $new_cooling_setpoint);

				push(@new_loopcontrols, 
				[ $new_loop_letter, $new_loopcontrol_letter, $new_loop_hour, 
				$new_max_heating_power, $new_min_heating_power, $new_max_cooling_power, 
				$new_min_cooling_power, $new_heating_setpoint, $new_cooling_setpoint ] );
			}

			my $countflow = 0;

			foreach my $elm (@flowbulk)
			{
				my @askflow = @{$elm};
				my $new_flow_letter = $askflow[0];
				my $new_flowcontrol_letter = $askflow[1];
				my $swing_flow_hour = $askflow[2];
				my $swing_flow_setpoint = $askflow[3];
				my $swing_flow_onoff = $askflow[4];
				if ( $swing_flow_onoff eq "ON") { $swing_flow_onoff = 1; }
				elsif ( $swing_flow_onoff eq "OFF") { $swing_flow_onoff = -1; }
				my $swing_flow_fraction = $askflow[5];

				my $countflow = 0; # IT IS FOR THE FOLLOWING FOREACH. LEAVE IT ATTACHED TO IT.
				foreach $each_flow (@flowcontrol) # THIS DISTRIBUTES THOSE NESTED DATA STRUCTURES IN A FLAT MODE TO PAIR THE INPUT FILE, USER DEFINED ONE.
				{
					my $countcontrol = 0;
					@thisflow = @{$each_flow};
					# my $letterfile = $letters[$countflow];
					foreach $elm (@thisflow)
					{
						my @control = @{$elm};
						# my $letterfilecontrol = $period_letters[$countcontrol];
						$flow_letter = $flowcontrol[$countflow][$countcontrol][0];
						$flowcontrol_letter = $flowcontrol[$countflow][$countcontrol][1];
						if ( ( $new_flow_letter eq $flow_letter ) and ($new_flowcontrol_letter eq $flowcontrol_letter ) )
						{
							$flow_hour__ = $flowcontrol[$countflow][$countcontrol][$flow_hour];
							$flow_setpoint__ = $flowcontrol[$countflow][$countcontrol][$flow_setpoint];
							$flow_onoff__ = $flowcontrol[$countflow][$countcontrol][$flow_onoff];
							if ( $flow_onoff__ eq "ON") { $flow_onoff__ = 1; }
							elsif ( $flow_onoff__ eq "OFF") { $flow_onoff__ = -1; }
							$flow_fraction__ = $flowcontrol[$countflow][$countcontrol][$flow_fraction];
						}
						$countcontrol++;
					}
					$countflow++;
				}
	
				my $pace_flow_hour =  ( $swing_flow_hour / ($stepsvar - 1) );
				my $floorvalue_flow_hour = ($flow_hour__ - ($swing_flow_hour / 2) );
				my $new_flow_hour = $floorvalue_flow_hour + ($countstep * $pace_flow_hour);

				my $pace_flow_setpoint =  ( $swing_flow_setpoint / ($stepsvar - 1) );
				my $floorvalue_flow_setpoint = ($flow_setpoint__ - ($swing_flow_setpoint / 2) );
				my $new_flow_setpoint = $floorvalue_flow_setpoint + ($countstep * $pace_flow_setpoint);

				my $pace_flow_onoff =  ( $swing_flow_onoff / ($stepsvar - 1) );
				my $floorvalue_flow_onoff = ($flow_onoff__ - ($swing_flow_onoff / 2) );
				my $new_flow_onoff = $floorvalue_flow_onoff + ($countstep * $pace_flow_onoff);

				my $pace_flow_fraction =  ( $swing_flow_fraction / ($stepsvar - 1) );
				my $floorvalue_flow_fraction = ($flow_fraction__ - ($swing_flow_fraction / 2) );
				my $new_flow_fraction = $floorvalue_flow_fraction + ($countstep * $pace_flow_fraction);

				$new_flow_hour = sprintf("%.2f", $new_flow_hour);
				$new_flow_setpoint = sprintf("%.2f", $new_flow_setpoint);
				$new_flow_onoff = sprintf("%.2f", $new_flow_onoff);
				$new_flow_fraction = sprintf("%.2f", $new_flow_fraction);

				push(@new_flowcontrols, 
				[ $new_flow_letter, $new_flowcontrol_letter, $new_flow_hour,  $new_flow_setpoint, $new_flow_onoff, $new_flow_fraction ] );
			}
			# HERE THE MODIFICATIONS TO BE EXECUTED ON EACH PARAMETERS ARE APPLIED TO THE MODELS THROUGH ESP-r.
			# FIRST, HERE THEY ARE APPLIED TO THE ZONE CONTROLS, THEN TO THE FLOW CONTROLS
		}
	} # END SUB calc_newcontrols

	print $_outfile_ "\@new_loopcontrols: " . Dumper(@new_loopcontrols) . "\n\n";

	apply_loopcontrol_changes(\@new_loopcontrols);
	apply_flowcontrol_changes(\@new_flowcontrols);

} # END SUB vary_controls.


calc_newctl($to, $stepsvar, $countop, $countstep, \@buildbulk, 
	\@flowbulk, \@loopcontrol, \@flowcontrol, $countvar, $fileconfig );


sub constrain_controls 
{	# IT READS CONTROL USER-IMPOSED CONSTRAINTS
	my ( $to, $filecon, $countop, $countstep, $swap, $swap2, $to_do, $countvar, $fileconfig ) = @_;
	
	my $zone_letter = $applytype[$countop][3];
	my @applytype = @$swap;
	my @constrain_controls = @$swap2;

	my $elm = $constrain_controls[$countop];
	my @group = @{$elm};
	my $sourcefile = $group[0];
	my $targetfile = $group[1];
	my $configfile = $group[2];
	my @sentletters = @{ $group[3] };
	my @sentperiod_letters = @{ $group[4] };
	
	my $sourceaddress = "$to$sourcefile";
	my $targetaddress = "$to$targetfile";
	my $configaddress = "$to$configfile";
	#@loopcontrol; @flowcontrol; @new_loopcontrols; @new_flowcontrols; # DON'T PUT "my" HERE. THEY ARE globsAL!!!
	my ( $semaphore_zone, $semaphore_dataloop, $semaphore_massflow, $semaphore_setpoint, $doline );
	my $count_controlmass = -1;
	my $countline = 0;
	
	my @letters;
	if (@sentletters) { @letters = @sentletters; }
	else 
	{
		@letters = ("e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "z"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	}
	
	my @period_letters;
	if (@sentperiod_letters) { @period_letters = @sentperiod_letters; }
	else 
	{
		@period_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	}
	
	my $loop_hour = 2; # NOTE: THE FOLLOWING VARIABLE NAMES ARE SHADOWED IN THE FOREACH LOOP BELOW, 
	# BUT ARE THE ONES USED IN THE OPT CONSTRAINTS FILES.
	my $max_heating_power = 3;
	my $min_heating_power = 4;
	my $max_cooling_power = 5,
	my $min_cooling_power = 6;
	my $heating_setpoint = 7;
	my $cooling_setpoint = 8;
	my $flow_hour = 2;
	my $flow_setpoint = 3;
	my $flow_onoff = 4;
	my $flow_fraction = 5;
	my ( $loop_letter, $loopcontrol_letter );
	my $countbuild = 0;
	my $countflow = 0;
	my $countcontrol = 0;	

	my ( @groupzone_letters, @zone_period_letters, @flow_letters, @fileloopbulk, @fileflowbulk );

	unless ($to_do eq "justwrite")
	{
		if ($countstep == 1)
		{
			print $_outfile_ "THIS\n";
			checkfile($sourceaddress, $targetaddress);
			read_controls($sourceaddress, $targetaddress, \@letters, \@period_letters);
			read_control_constraints($to, $stepsvar, 
			$countop, $countstep, $configaddress, \@loopcontrol, \@flowcontrol, \@temploopcontrol, \@tempflowcontrol, $countvar, $fileconfig );
		}
	}

	unless ($to_do eq "justread")
	{
		print $_outfile_ "THAT\n";
		apply_loopcontrol_changes( \@new_loopcontrol, \@temploopcontrol);
		apply_flowcontrol_changes(\@new_flowcontrol, \@tempflowcontrol);
	}

} # END SUB constrain_controls.


sub read_controls
{	# TO BE CALLED WITH: read_controls($sourceaddress, $targetaddress, \@letters, \@period_letters);
	# THIS MAKES THE CONTROL CONFIGURATION FILE BE READ AND THE NEEDED VALUES ACQUIRED.
	# NOTICE THAT CURRENTLY ONLY THE "basic control law" IS SUPPORTED.

	my ( $sourceaddress, $targetaddress, $swap, $swap2, $countvar ) = @_;
	
	my @letters = @$swap;
	my @period_letters = @$swap2;

	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourceaddress: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;
	my $countlines = 0;
	my $countloop = -1;
	my $countflow = -1;
	my $countflowcontrol = -1;
	my ( $countloopcontrol, $semaphore_building, $semaphore_loop, $loop_hour, $semaphore_loopcontrol, $semaphore_massflow,
		$flow_hour, $semaphore_flow, $semaphore_flowcontrol, $loop_letter, $loopcontrol_letter, $flow_letter, $flowcontrol_letter );

	foreach my $line (@lines)
	{
		if ( $line =~ /Control function/ )
		{
			$semaphore_loop = "yes";
			$countloopcontrol = -1;
			$countloop++;
			$loop_letter = $letters[$countloop];
		}
		if ( ($line =~ /ctl type, law/ ) )
		{
			$countloopcontrol++;
			my @row = split(/\s+/, $line);
			$loop_hour = $row[3];
			$semaphore_loopcontrol = "yes";
			$loopcontrol_letter = $period_letters[$countloopcontrol];
		}

		if ( ($semaphore_loop eq "yes") and ($semaphore_loopcontrol eq "yes") and ($line =~ /No. of data items/ ) ) 
		{  
			$doline = $countlines + 1;
		}

		if ( ($semaphore_loop eq "yes" ) and ($semaphore_loopcontrol eq "yes") and ($countlines == $doline) ) 
		{
			my @row = split(/\s+/, $line);
			my $max_heating_power = $row[1];
			my $min_heating_power = $row[2];
			my $max_cooling_power = $row[3];
			my $min_cooling_power = $row[4];
			my $heating_setpoint = $row[5];
			my $cooling_setpoint = $row[6];

			push(@{$loopcontrol[$countloop][$countloopcontrol]}, 
			$loop_letter, $loopcontrol_letter, $loop_hour, 
			$max_heating_power, $min_heating_power, $max_cooling_power, 
			$min_cooling_power, $heating_setpoint, $cooling_setpoint );

			$semaphore_loopcontrol = "no";
			$doline = "";
		}

		if ($line =~ /Control mass/ )
		{
			$semaphore_flow = "yes";
			$countflowcontrol = -1;
			$countflow++;
			$flow_letter = $letters[$countflow];
		}
		if ( ($line =~ /ctl type \(/ ) )
		{
			$countflowcontrol++;
			my @row = split(/\s+/, $line);
			$flow_hour = $row[3];
			$semaphore_flowcontrol = "yes";
			$flowcontrol_letter = $period_letters[$countflowcontrol];
		}

		if ( ($semaphore_flow eq "yes") and ($semaphore_flowcontrol eq "yes") and ($line =~ /No. of data items/ ) ) 
		{  
			$doline = $countlines + 1;
		}

		if ( ($semaphore_flow eq "yes" ) and ($semaphore_flowcontrol eq "yes") and ($countlines == $doline) ) 
		{
			my @row = split(/\s+/, $line);
			my $flow_setpoint = $row[1];
			my $flow_onoff = $row[2];
			my $flow_fraction = $row[3];
			push(@{$flowcontrol[$countflow][$countflowcontrol]}, 
			$flow_letter, $flowcontrol_letter, $flow_hour, $flow_setpoint, $flow_onoff, $flow_fraction);
			$semaphore_flowcontrol = "no";
			$doline = "";
		}
		$countlines++;
	}			
} # END SUB read_controls.


sub read_control_constraints
{
	#  #!/usr/bin/perl
	# THIS FILE CAN CONTAIN USER-IMPOSED CONSTRAINTS FOR CONTROLS TO BE READ BY OPT.
	# THE FOLLOWING VALUES CAN BE ADDRESSED IN THE OPT CONSTRAINTS CONFIGURATION FILE, 
	# SET BY THE PRESENT FUNCTION:
	# 1) $loopcontrol[$countop][$countloop][$countloopcontrol][$loop_hour] 
	# Where $countloop and  $countloopcontrol has to be set to a specified number in the OPT file for constraints.
	# 2) $loopcontrol[$countop][$countloop][$countloopcontrol][$max_heating_power] # Same as above.
	# 3) $loopcontrol[$countop][$countloop][$countloopcontrol][$min_heating_power] # Same as above.
	# 4) $loopcontrol[$countop][$countloop][$countloopcontrol][$max_cooling_power] # Same as above.
	# 5) $loopcontrol[$countop][$countloop][$countloopcontrol][$min_cooling_power] # Same as above.
	# 6) $loopcontrol[$countop][$countloop][$countloopcontrol][heating_setpoint] # Same as above.
	# 7) $loopcontrol[$countop][$countloop][$countloopcontrol][cooling_setpoint] # Same as above.
	# 8) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_hour] 
	# Where $countflow and  $countflowcontrol has to be set to a specified number in the OPT file for constraints.
	# 9) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_setpoint] # Same as above.
	# 10) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_onoff] # Same as above.
	# 11) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_fraction] # Same as above.
	# EXAMPLE : $flowcontrol[0][1][2][$flow_fraction] = 0.7
	# OTHER EXAMPLE: $flowcontrol[2][1][2][$flow_fraction] = $flowcontrol[0][2][1][$flow_fraction]
	# The $countop that is actuated is always the last, the one which is active. 
	# It would have therefore no sense writing $flowcontrol[1][1][2][$flow_fraction] = $flowcontrol[3][2][1][$flow_fraction].
	# Differentent $countops can be referred to the same zone. Different $countops just number mutations in series.
	# ALSO, THIS MAKES AVAILABLE TO THE USER INFORMATIONS ABOUT THE MORPHING STEP OF THE MODELS 
	# AND THE STEPS THE MODEL HAS TO FOLLOW. 
	# THIS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO THESE VARIABLES, 
	# WHICH COULD ALSO BE COMBINED WITH THE FOLLOWING ONES: 
	# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
	# $countop, WHICH TELLS THE PROGRAM WHAT OPERATION IS BEING EXECUTED IN THE CHAIN OF OPERATIONS 
	# THAT MAY BE EXECUTES AT EACH MORPHING PHASE. EACH $countop WILL CONTAIN ONE OR MORE ITERATION STEPS.
	# TYPICALLY, IT WILL BE USED FOR A ZONE, BUT NOTHING PREVENTS THAT SEVERAL OF THEM CHAINED ONE AFTER 
	# THE OTHER ARE APPLIED TO THE SAME ZONE.
	# $countstep, WHICH TELLS THE PROGRAM WHAT THE CURRENT ITERATION STEP IS.
	# $countvar, WHICH TELLS THE PROGRAM WHAT NUMBER OF DESIGN PARAMETER THE PROGRAM IS WORKING AT.
	
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $swap3, $swap4, $countvar, $fileconfig ) = @_;
	
	@loopcontrol = @$swap;
	@flowcontrol = @$swap2;
	@temploopcontrol = @$swap3;
	@tempflowcontrol = @$swap4;

	if (-e $configaddress) # TEST THIS, DDD
	{	# THIS APPLIES CONSTRAINST, THE FLATTEN THE HIERARCHICAL STRUCTURE OF THE RESULTS,
		# TO BE PREPARED THEN FOR BEING APPLIED TO CHANGE PROCEDURES. IT HAS TO BE TESTED.
		push (@loopcontrol, [@myloopcontrol]); #
		push (@flowcontrol, [@myflowcontrol]); #

		eval `cat $configaddress`;	# HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS 
		# IS EVALUATED, AND HERE BELOW CONSTRAINTS ARE PROPAGATED.	

		if (-e $constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
		# FOR PROPAGATION OF CONSTRAINTS

		@doloopcontrol = @{$loopcontrol[$#loopcontrol]}; #
		@doflowcontrol = @{$flowcontrol[$#flowcontrol]}; #

		shift (@doloopcontrol);
		shift (@doflowcontrol);

		sub flatten_loopcontrol_constraints
		{
			my @looptemp = @doloopcontrol;
			@new_loopcontrol = "";
			foreach my $elm (@looptemp)
			{
				my @loop = @{$elm};
				foreach my $elm (@loop)
				{
					my @loop = @{$elm};
					push (@new_loopcontrol, [@loop]);
				}
			}
		}
		flatten_loopcontrol_constraints;

		sub flatten_flowcontrol_constraints
		{
			my @flowtemp = @doflowcontrol;
			@new_flowcontrol = "";
			foreach my $elm (@flowtemp)
			{
				my @flow = @{$elm};
				foreach my $elm (@flow)
				{
					my @loop = @{$elm};
					push (@new_flowcontrol, [@flow]);
				}
			}
		}
		flatten_flowcontrol_constraints;

		shift @new_loopcontrol;
		shift @new_flowcontrol;
	}
} # END SUB read_control_constraints


sub apply_loopcontrol_changes
{ 	# TO BE CALLED WITH: apply_loopcontrol_changes($exeonfiles, \@new_loopcontrol);
	# THIS APPLIES CHANGES TO LOOPS IN CONTROLS (ZONES)
	my ( $swap, $swap2, $countvar ) = @_;
	
	my @new_loop_ctls = @$swap;
	my @temploopcontrol = @$swap2;
	
	my $countloop = 0;

	foreach my $elm (@new_loop_ctls)
	{
		my @loop = @{$elm};
		$new_loop_letter = $loop[0];
		$new_loopcontrol_letter = $loop[1];
		$new_loop_hour = $loop[2];
		$new_max_heating_power = $loop[3];
		$new_min_heating_power = $loop[4];
		$new_max_cooling_power = $loop[5];
		$new_min_cooling_power = $loop[6];
		$new_heating_setpoint = $loop[7];
		$new_cooling_setpoint = $loop[8];
		unless ( @{$new_loop_ctls[$countloop]} ~~ @{$temploopcontrol[$countloop]} )
		{
			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
j

$new_loop_letter
c
$new_loopcontrol_letter
1
$new_loop_hour
b
$new_max_heating_power
c
$new_min_heating_power
d
$new_max_cooling_power
e
$new_min_cooling_power
f
$new_heating_setpoint
g
$new_cooling_setpoint
-
y
-
-
-
n
d

-
y
y
-
-
YYY
";
			if ($exeonfiles eq "y") 
			{
				print `$printthis`;
			}
			print TOSHELL $printthis;
		}
		$countloop++;
	}
} # END SUB apply_loopcontrol_changes();


sub apply_flowcontrol_changes
{	# THIS HAS TO BE CALLED WITH: apply_flowcontrol_changes($exeonfiles, \@new_flowcontrols);
	# # THIS APPLIES CHANGES TO NETS IN CONTROLS
	my ( $swap, $swap2, $countvar ) = @_;
	
	my $countflow = 0;
	my @new_flowcontrols = @$swap;
	my @tempflowcontrol = @$swap2;

	foreach my $elm (@new_flowcontrols)
	{
		my @flow = @{$elm};
		$flow_letter = $flow[0];
		$flowcontrol_letter = $flow[1];
		$new_flow_hour = $flow[2];
		$new_flow_setpoint = $flow[3];
		$new_flow_onoff = $flow[4];
		$new_flow_fraction = $flow[5];
		unless ( @{$new_flowcontrols[$countflow]} ~~ @{$tempflowcontrol[$countflow]} )
		{
			my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
l

$flow_letter
c
$flowcontrol_letter
a
$new_flow_hour
$new_flow_setpoint $new_flow_onoff $new_flow_fraction
-
-
-
y
y
-
-
YYY
";
			if ($exeonfiles eq "y") # if ($exeonfiles eq "y") 
			{ 
				print `$printthis`;
			}

			print TOSHELL $printthis;
		}
		$countflow++;
	}
} # END SUB apply_flowcontrol_changes;
# END OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING CONTROLS
##############################################################################


##############################################################################
# BEGINNING OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING OBSTRUCTIONS	
sub constrain_obstructions # IT APPLIES CONSTRAINTS TO OBSTRUCTIONS
{
	# THIS CONSTRAINS OBSTRUCTION FILES. IT HAS TO BE CALLED FROM THE MAIN FILE WITH:
	# constrain_obstruction($to, $fileconfig, $stepsvar, $countop, $countstep, $exeonfiles, \@applytype, \@constrain_obstructions);
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $to_do, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @constrain_obstructions = @$swap2;
	
	say "Propagating constraints on obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @work_letters;
	#@obs;	# globsAL!

	foreach my $elm (@constrain_obstructions)
	{
		my @group = @{$elm};
		my $zone_letter = $group[0];
		my $sourcefile = $group[1];
		my $targetfile = $group[2];
		my $configfile_ = $group[3];
		my $sourceaddress = "$to$sourcefile";
		my $targetaddress = "$to$targetfile";
		my $configaddress = "$to$configfile";
		my @work_letters = @{$group[4]}; 
		my $actonmaterials = $group[5];
		my @sentobs_letters = @{$group[6]}; 
	
		unless ($to_do eq "justwrite")
		{
			checkfile($sourceaddress, $targetaddress);
			read_obstructions($to, $sourceaddress, $targetaddress, $configaddress, \@work_letters, $actonmaterials, $countvar, \@sentobs_letters);
			read_obs_constraints($to, $stepsvar, $countop, $countstep, $configaddress, $actonmaterials, \@tempobs, $countvar, $fileconfig  ); # IT WORKS ON THE VARIABLE @obs, WHICH IS globsAL.
		}

		unless ($to_do eq "justread")
		{
			apply_obs_constraints(\@doobs, \@obs_letters, \@work_letters, $zone_letter, $actonmaterials, \@tempobs);
		}
	}
} # END SUB constrain_obstructions


sub read_obstructions
{
	# THIS READS GEOMETRY FILES. # IT HAS TO BE CALLED WITH:
	# read_obstructions($to, $sourcefile, $targetfile, $configfiles, \@work_letters, $actonmaterials, $countvar);
	my ( $to, $sourceaddress, $targetaddress, $configaddress, $swap, $actonmaterials, $countvar, $swap2 ) = @_;
	
	my @obs_letters;
	
	my @work_letters = @$swap;
	my @sentobs_letters = @$swap2;
				
	open( SOURCEFILE, $sourceaddress) or die "Can't open $sourceaddress: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;

	my $count = 0;
	foreach my $line (@lines)
	{
		#$line =~ s/^\s+//; 
		if  ( $line =~ m/\*obs/ ) 
		{
			unless ( $line =~ m/\*obs =/ ) 
			{
				$count++;
			}
		}
	}
	
	if (@sentobs_letters)
	{
		@obs_letters = @sentobs_letters;
	}
	else
	{
		if ( $count > 21 )
		{																
			@obs_letters = ("e", "f", "g", "h", "i", "j", "k", "l", "m", "n", 
			"o", "0\nb\nf", "0\nb\ng", "0\nb\nh", "0\nb\ni", "0\nb\nj", "0\nb\nk", "0\nb\nm", 
			"0\nb\nn", "0\nb\no", "0\nb\n0\nb\nf","0\nb\n0\nb\ng",
			"0\nb\n0\nb\nh","0\nb\n0\nb\ni","0\nb\n0\nb\nj","0\nb\n0\nb\nk","0\nb\n0\nb\nl",
			"0\nb\n0\nb\nm","0\nb\n0\nb\nn","0\nb\n0\nb\no","0\nb\n0\nb\n0\nb\nf",
			"0\nb\n0\nb\n0\nb\ng","0\nb\n0\nb\n0\nb\nh","0\nb\n0\nb\n0\nb\ni","0\nb\n0\nb\n0\nb\nj",
			"0\nb\n0\nb\n0\nb\nk","0\nb\n0\nb\n0\nb\nl","0\nb\n0\nb\n0\nb\nm","0\nb\n0\nb\n0\nb\nn",
			"0\nb\n0\nb\n0\nb\no");
		}
		else
		{	
			@obs_letters = ("e", "f", "g", "h", "i", "j", "k", "l", "m", 
			"n", "o", "0\nf", "0\ng", "0\nh", "0\ni", "0\nj", "0\nk", "0\nl", 
			"0\nm", "0\nn", "0\no");
		}
	}

	my $count = 0;
	foreach my $line (@lines)
	{
		if  ( $line =~ m/\*obs/ ) 
		{
			unless ( $line =~ m/\*obs =/ ) 
			{
				#$line =~ s/^\s+//; 
				my @rowelements = split(/,/, $line);	
				push (@obs, [ $rowelements[1], $rowelements[2], $rowelements[3], 
				$rowelements[4], $rowelements[5], $rowelements[6], 
				$rowelements[7], $rowelements[8], $rowelements[9], 
				$rowelements[10], $rowelements[11], $rowelements[12], $obs_letters[$count] ] );
				$count++;
			}
		}
	}
} # END SUB read_obstructions


sub read_obs_constraints
{	
	# THE VARIABLE @obs REGARDS OBSTRUCTION USER-IMPOSED CONSTRAINTS
	# THIS CONSTRAINT CONFIGURATION FILE MAKES AVAILABLE TO THE USER THE FOLLOWING VARIABLES:
	# $obs[$countop][$obs_number][$x], $obs[$countop][$obs_number][$y], $obs[$countop][$obs_number][$y]
	# $obs[$countop][$obs_number][$width], $obs[$countop][$obs_number][$depth], $obs[$countop][$obs_number][$height]
	# $obs[$countop][$obs_number][$z_rotation], $obs[$countop][$obs_number][$y_rotation], 
	# $obs[$countop][$obs_number][$tilt], $obs[$countop][$obs_number][$opacity], $obs[$countop][$obs_number][$material], 
	# EXAMPLE: $obs[0][2][$x] = 2. THIS MEANS: AT COUNTERZONE 0, COORDINATE x OF OBSTRUCTION HAS TO BE SET TO 2.
	# OTHER EXAMPLE: $obs[0][2][$x] = $obs[2][2][$y].
	# The $countop that is actuated is always the last, the one which is active. 
	# There would be therefore no sense in writing $obs[0][4][$x] =  $obs[1][2][$y].
	# Differentent $countops can be referred to the same zone. Different $countops just number mutations in series.
	# NOTE THAT THE MATERIAL TO BE SPECIFIED IS A MATERIAL LETTER, BETWEEN QUOTES. EXAMPLE: $obs[1][$material] = "a".
	#  $tilt IS PRESENTLY UNUSED.
	# ALSO, THIS MAKES AVAILABLE TO THE USER INFORMATIONS ABOUT THE MORPHING STEP OF THE MODELS 
	# AND THE STEPS THE MODEL HAVE TO FOLLOW.
	# THIS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO THESE VARIABLES, 
	# WHICH COULD ALSO BE COMBINED WITH THE FOLLOWING ONES: 
	# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
	# $countop, WHICH TELLS THE PROGRAM WHAT OPERATION IS BEING EXECUTED IN THE CHAIN OF OPERATIONS 
	# THAT MAY BE EXECUTES AT EACH MORPHING PHASE. EACH $countop WILL CONTAIN ONE OR MORE ITERATION STEPS.
	# TYPICALLY, IT WILL BE USED FOR A ZONE, BUT NOTHING PREVENTS THAT SEVERAL OF THEM CHAINED ONE AFTER 
	# THE OTHER ARE APPLIED TO THE SAME ZONE.
	# $countstep, WHICH TELLS THE PROGRAM WHAT THE CURRENT ITERATION STEP IS.
	# $countvar, WHICH TELLS THE PROGRAM WHAT NUMBER OF DESIGN PARAMETER THE PROGRAM IS WORKING AT.
	my ( $to, $stepsvar, $countop, $countstep, $configaddress, $actonmaterials, $swap, $countvar, $fileconfig ) = @_;
	
	@tempobs = @$swap;

	my $obs_letter = 13;
	my $x = 1;
	my $y = 2;
	my $z = 3;
	my $width = 4;
	my $depth = 5;
	my $height = 6;
	my $z_rotation = 7;
	my $y_rotation = 8;
	my $tilt = 9; # UNUSED
	my $opacity = 10;
	my $name = 11; # NOT TO BE CHANGED
	my $material = 12;
	if (-e $configaddress)
	{	
		unshift (@obs, []);	
		push (@obs, [@myobs]); #	
		eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED.

		if (-e $constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
		# FOR PROPAGATION OF CONSTRAINTS

		@doobs = @{$obs[$#obs]}; #
		shift @doobs;
	}
} # END SUB read_geo_constraints


sub apply_obs_constraints
{
	# IT APPLY USER-IMPOSED CONSTRAINTS TO A GEOMETRY FILES VIA SHELL
	# IT HAS TO BE CALLED WITH: 
	# apply_geo_constraints(\@obs, \@obsletters, \@work_letters, \$exeonfiles, \$zone_letter, $actonmaterials);
	my ( $swap, $swap2, $swap3, $zone_letter, $actonmaterials, $swap4, $countvar ) = @_;
	
	my @obs = @$swap;
	my @obs_letters = @$swap2;
	my @work_letters = @$swap3;
	my @tempobs = @$swap4;
	

	my $countobs = 0;
	print $_outfile_ "OBS_LETTERS IN APPLY" . Dumper(@obs_letters) . "\n\n";
	foreach my $ob (@obs)
	{
		my $obs_letter = $obs_letters[$countobs];
		if ( ( @work_letters eq "") or ($obs_letter  ~~ @work_letters))
		{
			my @obstr = @{$ob};
			my $x = $obstr[0];
			my $y = $obstr[1];
			my $z = $obstr[2];
			my $width = $obs[3];
			my $depth = $obs[4];
			my $height = $obs[5];
			my $z_rotation = $obs[6];
			my $y_rotation = $obs[7];
			my $tilt = $obs[8];
			my $opacity = $obs[9];
			my $name = $obs[10];
			my $material = $obs[11];
			unless
			( 
				( @{$obs[$countobs]} ~~ @{$tempobs[$countobs]} ) 
			)
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$obs_letter
a
a
$x $y $z
b
$width $depth $height
c
$z_rotation
d
$y_rotation
e # HERE THE DATUM IS STILL UNUSED. WHEN IT WILL, A LINE MUST BE ADDED WITH THE VARIABLE $tilt.
h
$opacity
-
-
c
-
c
-
-
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{
					print `$printthis`;
				}

				print TOSHELL $printthis;
			}

			my $obs_letter = $obs_letters[$countobs];
			if ($obs_letter  ~~ @work_letters)
			{
				if ($actonmaterials eq "y")
				{	
					my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
c
a
$zone_letter
h
a
$obs_letter
g
$material
-
-
-
c
-
c
-
-
-
-
YYY
";		
					if ($exeonfiles eq "y") 
					{
						print `$printthis`;
					}

					print TOSHELL $printthis;
				}
			}
		}
		$countobs++;
	}
} # END SUB apply_obs_constraints
##############################################################################
# END OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING OBSTRUCTIONS


##############################################################################
# BEGINNING OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING THE MASS-FLOW NETWORKS
sub vary_net
{  	# IT IS CALLED FROM THE MAIN FILE
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @vary_net = @$swap2;
	
	say "Propagating constraints on networks for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $activezone = $applytype[$countop][3];
	my ($semaphore_node, $semaphore_component, $node_letter);
	my $count_component = -1;
	my $countline = 0;
	my @node_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	my @component_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	# NOTE: THE FOLLOWING VARIABLE NAMES ARE SHADOWED IN THE FOREACH LOOP BELOW, 
	# BUT ARE THE ONES USED IN THE OPT CONSTRAINTS FILES.

	my @group = @{$vary_net[$countop]};
	my $sourcefile = $group[0];
	my $targetfile = $group[1];
	my $configfile = $group[2];
	my @nodebulk = @{$group[3]};
	my @componentbulk = @{$group[4]};
	my $countnode = 0;
	my $countcomponent = 0;

	my $sourceaddress = "$to$sourcefile";
	my $targetaddress = "$to$targetfile";
	my $configaddress = "$to$configfile";	

	#@node; @component; # PLURAL. DON'T PUT "my" HERE!
	#@new_nodes; @new_components; # DON'T PUT "my" HERE.

	my @flow_letters;

	checkfile($sourceaddress, $targetaddress);

	if ($countstep == 1)
	{
		read_net($sourceaddress, $targetaddress, \@node_letters, \@component_letters);
	}

	sub calc_newnet
	{	# TO BE CALLED WITH: calc_newnet($to, $fileconfig, $stepsvar, $countop, $countstep, \@nodebulk, \@componentbulk, \@node_, \@component);
		# THIS COMPUTES CHANGES TO BE MADE TO CONTROLS BEFORE PROPAGATION OF CONSTRAINTS
		my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $swap3, $swap4, $countvar, $fileconfig ) = @_;
		
		my @nodebulk = @$swap;
		my @componentbulk = @$swap2;
		my @node = @$swap3; # PLURAL
		my @component = @$swap4; # PLURAL
		
		my ( @new_volumes_or_surfaces, @node_heights_or_cps, @new_azimuths, @boundary_heights );

		# HERE THE MODIFICATIONS TO BE EXECUTED ON EACH PARAMETERS ARE CALCULATED.
		if ($stepsvar == 0) {$stepsvar = 1;}
		if ($stepsvar > 1) 
		{
			foreach $each_nodebulk (@nodebulk)
			{
				my @asknode = @{$each_nodebulk};
				my $new_node_letter = $asknode[0];
				my $new_fluid = $asknode[1];
				my $new_type = $asknode[2];
				my $new_zone = $activezone;
				my $swing_height = $asknode[3];
				my $swing_data_2 = $asknode[4];
				my $new_surface = $asknode[5];
				my @askcp = @{$asknode[6]};
				my ($height__, $data_2__, $data_1__, $new_cp);					
				my $countnode = 0; #IT IS FOR THE FOLLOWING FOREACH. LEAVE IT ATTACHED TO IT.
				foreach $each_node (@node)
				{
					@node_ = @{$each_node};
					my $node_letter = $node_[0]; 
					if ( $new_node_letter eq $node_letter ) 
					{
						$height__ = $node_[3];
						$data_2__ = $node_[4];
						$data_1__ = $node_[5];
						$new_cp = $askcp[$countstep-1];
					}
					$countnode++;
				}
				my $height = ( $swing_height / ($stepsvar - 1) );
				my $floorvalue_height = ($height__ - ($swing_height / 2) );
				my $new_height = $floorvalue_height + ($countstep * $pace_height);
				$new_height = sprintf("%.3f", $height);
				if ($swing_height == 0) { $new_height = ""; }

				my $pace_data_2 =  ( $swing_data_2 / ($stepsvar - 1) );
				my $floorvalue_data_2 = ($data_2__ - ($swing_data_2 / 2) );
				my $new_data_2 = $floorvalue_data_2 + ($countstep * $pace_data_2);
				$new_data_2 = sprintf("%.3f", $new_data_2);
				if ($swing_data_2 == 0) { $new_data_2 = ""; }

				my $pace_data_1 =  ( $swing_data_1 / ($stepsvar - 1) ); # UNUSED
				my $floorvalue_data_1 = ($data_1__ - ($swing_data_1 / 2) );
				my $new_data_1 = $floorvalue_data_1 + ($countstep * $pace_data_1);
				$new_data_1  = sprintf("%.3f", $new_data_1);
				if ($swing_data_1 == 0) { $new_data_1 = ""; }

				push(@new_nodes, 
				[ $new_node_letter, $new_fluid, $new_type, $new_zone, $new_height, $new_data_2, $new_surface, $new_cp ] );
			}

			foreach $each_componentbulk (@componentbulk)
			{
				my @askcomponent = @{$each_componentbulk};
				my $new_component_letter = $askcomponent[0];

				my $new_type = $askcomponent[1];
				my $swing_data_1 = $askcomponent[2];
				my $swing_data_2 = $askcomponent[3];
				my $swing_data_3 = $askcomponent[4];	
				my $swing_data_4 = $askcomponent[5];
				my $component_letter;				
				my $countcomponent = 0;    #IT IS FOR THE FOLLOWING FOREACH.
				my ($new_type, $data_1__, $data_2__, $data_3__, $data_4__ );
				foreach $each_component (@component) # PLURAL
				{
					@component_ = @{$each_component};
					$component_letter = $component_letters[$countcomponent]; 
					if ( $new_component_letter eq $component_letter ) 
					{
						$new_component_letter = $component_[0];
						$new_fluid = $component_[1];
						$new_type = $component_[2];
						$data_1__ = $component_[3];
						$data_2__ = $component_[4];
						$data_3__ = $component_[5];
						$data_4__ = $component_[6];
					}
					$countcomponent++;
				}

				my $pace_data_1 =  ( $swing_data_1 / ($stepsvar - 1) ); 
				my $floorvalue_data_1 = ($data_1__ - ($swing_data_1 / 2) );
				my $new_data_1 = $floorvalue_data_1 + ($countstep * $pace_data_1);
				if ($swing_data_1 == 0) { $new_data_1 = ""; }

				my $pace_data_2 =  ( $swing_data_2 / ($stepsvar - 1) );
				my $floorvalue_data_2 = ($data_2__ - ($swing_data_2 / 2) );
				my $new_data_2 = $floorvalue_data_2 + ($countstep * $pace_data_2);
				if ($swing_data_2 == 0) { $new_data_2 = ""; }

				my $pace_data_3 =  ( $swing_data_3 / ($stepsvar - 1) ); 
				my $floorvalue_data_3 = ($data_3__ - ($swing_data_3 / 2) );
				my $new_data_3 = $floorvalue_data_3 + ($countstep * $pace_data_3 );
				if ($swing_data_3 == 0) { $new_data_3 = ""; }

				my $pace_data_4 =  ( $swing_data_4 / ($stepsvar - 1) ); 
				my $floorvalue_data_4 = ($data_4__ - ($swing_data_4 / 2) );
				my $new_data_4 = $floorvalue_data_4 + ($countstep * $pace_data_4 );
				if ($swing_data_4 == 0) { $new_data_4 = ""; }

				$new_data_1 = sprintf("%.3f", $new_data_1);
				$new_data_2 = sprintf("%.3f", $new_data_2);
				$new_data_3 = sprintf("%.3f", $new_data_3);
				$new_data_4 = sprintf("%.3f", $new_data_4);
				$new_data_4 = sprintf("%.3f", $new_data_4);

				push(@new_components, [ $new_component_letter, $new_fluid, $new_type, $new_data_1, $new_data_2, $new_data_3, $new_data_4 ] );
			}
		}
	} # END SUB calc_newnet

	calc_newnet($to, $stepsvar, $countop, $countstep, \@nodebulk, \@componentbulk, \@node, \@component, $countvar, $fileconfig  );	# PLURAL

	apply_node_changes(\@new_nodes);
	apply_component_changes(\@new_components);

} # END SUB vary_net.


sub read_net
{
	my ( $sourceaddress, $targetaddress, $swap, $swap2, $countvar ) = @_;
	
	# checkfile($sourceaddress, $targetaddress); # THIS HAS TO BE _FIXED!_
	my @node_letters = @$swap;
	my @component_letters = @$swap2;

	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourcefile : $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;
	my $countlines = 0;
	my $countnode = -1;
	my $countcomponent = -1;
	my $countcomp = 0;
	my $semaphore_node = "no";
	my $semaphore_component = "no";
	my $semaphore_connection = "no";
	my ($component_letter, $type, $data_1, $data_2, $data_3, $data_4);
	foreach my $line (@lines)
	{
		if ( $line =~ m/Fld. Type/ )
		{
			$semaphore_node = "yes";
		}
		if ( $semaphore_node eq "yes" )
		{
			$countnode++;
		}
		if ( $line =~ m/Type C\+ L\+/ )
		{
			$semaphore_component = "yes";
			$semaphore_node = "no";
		}



		if ( ($semaphore_node eq "yes") and ( $semaphore_component eq "no" ) and ( $countnode >= 0))
		{
			$line =~ s/^\s+//; 
			my @row = split(/\s+/, $line);
			my $node_letter = $node_letters[$countnode];
			my $fluid = $row[1];
			my $type = $row[2];
			my $height = $row[3];
			my $data_2 = $row[6]; # volume or azimuth
			my $data_1 = $row[5]; #surface
			push(@node, [ $node_letter, $fluid, $type, $height, $data_2, $data_1 ] ); # PLURAL
		}

		if ( $semaphore_component eq "yes" )
		{
			$countcomponent++;
		}

		if ( $line =~ m/\+Node/ )
		{
			$semaphore_connection = "yes";
			$semaphore_component = "no";
			$semaphore_node = "no";
		}

		if ( ($semaphore_component eq "yes") and ( $semaphore_connection eq "no" ) and ( $countcomponent > 0))
		{
			$line =~ s/^\s+//; 
			my @row = split(/\s+/, $line);
			if ($countcomponent % 2 == 1) # $number is odd 
			{ 
				$component_letter = $component_letters[$countcomp];
				$fluid = $row[0];
				$type = $row[1];
				if ($type eq "110") { $type = "k";}
				if ($type eq "120") { $type = "l";}
				if ($type eq "130") { $type = "m";}
				$countcomp++;
			}
			else # $number is even 
			{ 
				$data_1 = $row[1];
				$data_2 = $row[2];
				$data_3 = $row[3];
				$data_4 = $row[4];
				push( @component, [ $component_letter, $fluid, $type, $data_1, $data_2, $data_3, $data_4 ] ); # PLURAL
			}

		}

		$countlines++;
	}
} # END SUB read_controls.


sub apply_node_changes
{ 	# TO BE CALLED WITH: apply_node_changes($exeonfiles, \@new_nodes);
	# THIS APPLIES CHANGES TO NODES IN NETS
	my ( $swap, $swap2, $countvar ) = @_;
	
	my @new_nodes = @$swap;
	my @tempnodes = @$swap2;

	my $countnode = 0;
	foreach my $elm (@new_nodes)
	{
		my @node_ = @{$elm};
		my $new_node_letter = $node_[0];
		my $new_fluid = $node_[1];
		my $new_type = $node_[2];
		my $new_zone = $node_[3];
		my $new_height = $node_[4];
		my $new_data_2 = $node_[5];
		my $new_surface = $node_[6];
		my $new_cp = $node_[7];

		unless ( @{$new_nodes[$countnode]} ~~ @{$tempnodes[$countnode]} )
		{
			if ($new_type eq "a" ) # IF NODES ARE INTERNAL
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
e
c

n
c
$new_node_letter

$new_fluid
$new_type
y
$new_zone
$new_data_2
$new_height
a

-
-
y

y
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{
					print `$printthis`;
				}
				print TOSHELL $printthis;
			}

			if ($new_type eq "e" ) # IF NODES ARE BOUNDARY ONES, WIND-INDUCED
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
e
c

n
c
$new_node_letter

$new_fluid
$new_type
$new_zone
$new_surface
$new_cp
y
$new_data_2
$new_height
-
-
y

y
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{
					print `$printthis`;
				}
				print TOSHELL $printthis;
			}
		}
		$countnode++;
	}
} # END SUB apply_node_changes;


sub apply_component_changes
{ 	# TO BE CALLED WITH: apply_component_changes($exeonfiles, \@new_components);
	# THIS APPLIES CHANGES TO COMPONENTS IN NETS
	my ( $swap, $swap2, $countvar ) = @_;
	
	my @new_components = @$swap; # [ $new_component_letter, $new_type, $new_data_1, $new_data_2, $new_data_3, $new_data_4 ]
	my @tempcomponents = @$swap2;

	my $countcomponent = 0;
	foreach my $elm (@new_components)
	{
		my @component_ = @{$elm};
		my $new_component_letter = $component_[0];
		my $new_fluid = $component_[1];
		my $new_type = $component_[2];
		my $new_data_1 = $component_[3];
		my $new_data_2 = $component_[4];
		my $new_data_3 = $component_[5];
		my $new_data_4 = $component_[6];

		unless
		( @{$new_components[$countcomponents]} ~~ @{$tempcomponents[$countcomponents]} )
		{
			if ($new_type eq "k" ) # IF THE COMPONENT IS A GENERIC OPENING
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
e
c

n
d
$new_component_letter
$new_fluid
$new_type
-
$new_data_1
-
-
y

y
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{
					print `$printthis`;
				}
				print TOSHELL $printthis;
			}

			if ($new_type eq "l" ) # IF THE COMPONENT IS A CRACK
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
e
c

n
d
$new_component_letter
$new_fluid
$new_type
-
$new_data_1 $new_data_2
-
-
y

y
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{
					print `$printthis`;
				}
				print TOSHELL $printthis;
			}

			if ($new_type eq "m" ) # IF THE COMPONENT IS A DOOR
			{
				my $printthis =
"prj -file $to/cfg/$fileconfig -mode script<<YYY

m
e
c

n
d
$new_component_letter
$new_fluid
$new_type
-
$new_data_1 $new_data_2 $new_data_3 $new_data_4
-
-
y

y
-
-
YYY
";
				if ($exeonfiles eq "y") 
				{
					print `$printthis`;
				}
				print TOSHELL "$printthis";
			}
		}
		$countcomponent++;
	}
} # END SUB apply_component_changes;


sub constrain_net 
{	# IT ALLOWS TO MANIPULATE USER-IMPOSED CONSTRAINTS REGARDING NETS
	my ( $to, $stepsvar, $countop, $countstep, $swap, $swap2, $to_do, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @constrain_net = @$swap2;

	my $elm = $constrain_net[$countop];
	my @group = @{$elm};
	my $sourcefile = $group[0];
	my $targetfile = $group[1];
	my $configfile = $group[2];
	my @nodebulk = @{$group[3]};
	my @componentbulk = @{$group[4]};
	my $sourceaddress = "$to$sourcefile";
	my $targetaddress = "$to$targetfile";
	my $configaddress = "$to$configfile";

	my $node = 0;
	my $fluid = 1;
	my $type = 2;
	my $height = 3;
	my $volume = 4;
	my $volume = 4;
	my $azimuth = 4;
	my $component = 0;
	my $area = 3;
	my $width = 4;
	my $length = 5;
	my $door_width = 4;
	my $door_height = 5;
	my $door_nodeheight = 6;
	my $door_discharge = 7;

	my $activezone = $applytype[$countop][3];
	my ($semaphore_node, $semaphore_component, $node_letter);
	my $count_component = -1;
	my $countline = 0;
	my @node_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	my @component_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # CHECK IF THE LAST LETTERS ARE CORRECT, ZZZ
	my $countnode = 0;
	my $countcomponent = 0;

	#@node; @component; # PLURAL! DON'T PUT "MY" HERE. globsAL.
	#@new_nodes; @new_components; # DON'T PUT "my" HERE. THEY ARE globsAL!!!

	unless ($to_do eq "justwrite")
	{
		checkfile($sourceaddress, $targetaddress);
		if ($countstep == 1)
		{
			read_net($sourceaddress, $targetaddress, \@node_letters, \@component_letters);
			read_net_constraints
			($to, $stepsvar, $countop, $countstep, $configaddress, \@node, \@component, \@tempnode, \@tempcomponent, $countvar, $fileconfig  ); # PLURAL
		}
	}

	unless ($to_do eq "justread")
	{
		apply_node_changes(\@donode, \@tempnode); #PLURAL
		apply_component_changes(\@docomponent, \@tempcomponent);
	}
} # END SUB constrain_net.


sub read_net_constraints
{
	my ( $to, $stepsvar, $countop, $countstep, $configaddress, $swap, $swap2, $swap3, $swap4, $countvar, $fileconfig ) = @_;
	
	@node = @$swap; # PLURAL
	@component = @$swap2;
	@tempnode = @$swap3;
	@tempcomponent = @$swap4;

	unshift (@node, []); # PLURAL
	unshift (@component, []);
	if (-e $configaddress) # TEST THIS
	{	# THIS APPLIES CONSTRAINST, THE FLATTEN THE HIERARCHICAL STRUCTURE OF THE RESULTS,
		# TO BE PREPARED THEN FOR BEING APPLIED TO CHANGE PROCEDURES. IT IS TO BE TESTED.

		push (@node, [@mynode]); #
		push (@component, [@mycomponent]); #

		eval `cat $configaddress`;	# HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS 
		# IS EVALUATED, AND HERE BELOW CONSTRAINTS ARE PROPAGATED.
		# THIS FILE CAN CONTAIN USER-IMPOSED CONSTRAINTS FOR MASS-FLOW NETWORKS TO BE READ BY OPT.
		# IT MAKES AVAILABLE VARIABLES REGARDING THE SETTING OF NODES IN A NETWORK.
		# CURRENTLY: INTERNAL UNKNOWN AIR NODES AND BOUNDARY WIND-CONCERNED NODES.
		# IT MAKES AVAILABLE VARIABLES REGARDING COMPONENTS
		# CURRENTLY: WINDOWS, CRACKS, DOORS.
		# ALSO, THIS MAKES AVAILABLE TO THE USER INFORMATIONS ABOUT THE MORPHING STEP OF THE MODELS.
		# SPECIFICALLY, THE FOLLOWING VARIABLES WHICH REGARD BOTH INTERNAL AND BOUNDARY NODES.
		# NOTE THAT "node_number" IS THE NUMBER OF THE NODE IN THE ".afn" ESP-r FILE. 
		# $node[$countop][node_number][$node]. # EXAMPLE: $node[0][3][$node]. THIS IS THE LETTER OF THE THIRD NODE, 
		# AT THE FIRST CONTERZONE (NUMBERING STARTS FROM 0)
		# $node[$countop][node_number][$type]
		# $node[$countop][node_number][$height]. # EXAMPLE: $node[0][3][$node]. THIS IS THE HEIGHT OF THE 3RD NODE AT THE FIRST COUNTERZONE
		# THEN IT MAKES AVAILABLE THE FOLLOWING VARIABLES REGARDING NODES:
		# $node[$countop][node_number][$volume] # REGARDING INTERNAL NODES
		# $node[$countop][node_number][$azimut] # REGARDING BOUNDARY NODES
		# THEN IT MAKE AVAILABLE THE FOLLOWING VARIABLES REGARDING COMPONENTS:
		# $node[$countop][node_number][$area] # REGARDING SIMPLE OPENINGS
		# $node[$countop][node_number][$width] # REGARDING CRACKS
		# $node[$countop][node_number][$length] # REGARDING CRACKS
		# $node[$countop][node_number][$door_width] # REGARDING DOORS
		# $node[$countop][node_number][$door_height] # REGARDING DOORS
		# $node[$countop][node_number][$door_nodeheight] # REGARDING DOORS
		# $node[$countop][node_number][$door_discharge] # REGARDING DOORS (DISCHARGE FACTOR)
		# ALSO, THIS MAKES AVAILABLE TO THE USER INFORMATIONS ABOUT THE MORPHING STEP OF THE MODELS 
		# AND THE STEPS THE MODEL HAVE TO FOLLOW.
		# THIS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO THESE VARIABLES, 
		# WHICH COULD ALSO BE COMBINED WITH THE FOLLOWING VARIABLES 
		# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
		# $countop, WHICH TELLS THE PROGRAM WHAT OPERATION IS BEING EXECUTED IN THE CHAIN OF OPERATIONS 
		# THAT MAY BE EXECUTES AT EACH MORPHING PHASE. EACH $countop WILL CONTAIN ONE OR MORE ITERATION STEPS.
		# TYPICALLY, IT WILL BE USED FOR A ZONE, BUT NOTHING PREVENTS THAT SEVERAL OF THEM CHAINED ONE AFTER 
		# THE OTHER ARE APPLIED TO THE SAME ZONE.
		# $countstep, WHICH TELLS THE PROGRAM WHAT THE CURRENT ITERATION STEP IS.
		# $countvar, WHICH TELLS THE PROGRAM WHAT NUMBER OF DESIGN PARAMETER THE PROGRAM IS WORKING AT.
		# The $countop that is actuated is always the last, the one which is active. 
		# It would have therefore no sense writing $node[0][3][$node] =  $node[1][3][$node].
		# Differentent $countops can be referred to the same zone. Different $countops just number mutations in series.

		if (-e $constrain) { eval ($constrain); } # HERE THE INSTRUCTION WRITTEN IN THE OPT CONFIGURATION FILE CAN BE SPEFICIED
		# FOR PROPAGATION OF CONSTRAINTS

		@donode = @{$node[$#node]}; #
		@docomponent = @{$component[$#component]}; #

		shift (@donode);
		shift (@docomponent);
	}
} # END SUB read_net_constraints
##############################################################################
# END OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING MASS-FLOW NETWORKS



##############################################################################
# BEGINNING OF SECTION DEDICATED TO GENERIC FUNCTIONS FOR PROPAGATING CONSTRAINTS
sub propagate_constraints
{
	# THIS FUNCTION ALLOWS TO MANIPULATE COMPOUND USER-IMPOSED CONSTRAINTS.
	# IT COMPOUNDS ALL FOUR PRINCIPAL PROPAGATION TYPES. THAT MEANS THAT ONE COULD DO
	# ANY TYPE OF THE AVAILABLE PROPAGATIONS JUST USING THIS FUNCTION.
	# IT MAKES AVAILABLE TO THE USER THE FOLLOWING VARIABLES FOR MANIPULATION.

	# REGARDING GEOMETRY:
	# $v[$countop][$number][$x], $v[$countop][$number][$y], $v[$countop][$number][$z]. EXAMPLE: $v[0][4][$x] = 1. 
	# OR: @v[0][4][$x] =  @v[0][4][$y]. OR EVEN: @v[1][4][$x] =  @v[0][3][$z].

	# REGARDING OBSTRUCTIONS:
	# $obs[$countop][$obs_number][$x], $obs[$countop][$obs_number][$y], $obs[$countop][$obs_number][$y]
	# $obs[$countop][$obs_number][$width], $obs[$countop][$obs_number][$depth], $obs[$countop][$obs_number][$height]
	# $obs[$countop][$obs_number][$z_rotation], $obs[$countop][$obs_number][$y_rotation], 
	# $obs[$countop][$obs_number][$tilt], $obs[$countop][$obs_number][$opacity], $obs[$countop][$obs_number][$material], 
	# EXAMPLE: $obs[0][2][$x] = 2. THIS MEANS: AT COUNTERZONE 0, COORDINATE x OF OBSTRUCTION HAS TO BE SET TO 2.
	# OTHER EXAMPLE: $obs[0][2][$x] = $obs[2][2][$y].
	# NOTE THAT THE MATERIAL TO BE SPECIFIED IS A MATERIAL LETTER, BETWEEN QUOTES! EXAMPLE: $obs[1][$material] = "a".
	#  $tilt IS PRESENTLY UNUSED.

	# REGARDING MASS-FLOW NETWORKS:
	# @node and @component.
	# CURRENTLY: INTERNAL UNKNOWN AIR NODES AND BOUNDARY WIND-CONCERNED NODES.
	# IT MAKES AVAILABLE VARIABLES REGARDING COMPONENTS
	# CURRENTLY: WINDOWS, CRACKS, DOORS.
	# ALSO, THIS MAKES AVAILABLE TO THE USER INFORMATIONS ABOUT THE MORPHING STEP OF THE MODELS.
	# SPECIFICALLY, THE FOLLOWING VARIABLES WHICH REGARD BOTH INTERNAL AND BOUNDARY NODES.
	# NOTE THAT "node_number" IS THE NUMBER OF THE NODE IN THE ".afn" ESP-r FILE. 
	# 1) $loopcontrol[$countop][$countloop][$countloopcontrol][$loop_hour] 
	# Where $countloop and  $countloopcontrol has to be set to a specified number in the OPT file for constraints.
	# 2) $loopcontrol[$countop][$countloop][$countloopcontrol][$max_heating_power] # Same as above.
	# 3) $loopcontrol[$countop][$countloop][$countloopcontrol][$min_heating_power] # Same as above.
	# 4) $loopcontrol[$countop][$countloop][$countloopcontrol][$max_cooling_power] # Same as above.
	# 5) $loopcontrol[$countop][$countloop][$countloopcontrol][$min_cooling_power] # Same as above.
	# 6) $loopcontrol[$countop][$countloop][$countloopcontrol][heating_setpoint] # Same as above.
	# 7) $loopcontrol[$countop][$countloop][$countloopcontrol][cooling_setpoint] # Same as above.
	# 8) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_hour] 
	# Where $countflow and  $countflowcontrol has to be set to a specified number in the OPT file for constraints.
	# 9) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_setpoint] # Same as above.
	# 10) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_onoff] # Same as above.
	# 11) $flowcontrol[$countop][$countflow][$countflowcontrol][$flow_fraction] # Same as above.
	# EXAMPLE : $flowcontrol[0][1][2][$flow_fraction] = 0.7
	# OTHER EXAMPLE: $flowcontrol[2][1][2][$flow_fraction] = $flowcontrol[0][2][1][$flow_fraction]

	# REGARDING CONTROLS:
	# IT MAKES AVAILABLE VARIABLES REGARDING COMPONENTS
	# CURRENTLY: WINDOWS, CRACKS, DOORS.
	# ALSO, THIS MAKES AVAILABLE TO THE USER INFORMATIONS ABOUT THE MORPHING STEP OF THE MODELS.
	# SPECIFICALLY, THE FOLLOWING VARIABLES WHICH REGARD BOTH INTERNAL AND BOUNDARY NODES.
	# NOTE THAT "node_number" IS THE NUMBER OF THE NODE IN THE ".afn" ESP-r FILE. 
	# $node[$countop][node_number][$node]. # EXAMPLE: $node[0][3][$node]. THIS IS THE LETTER OF THE THIRD NODE, 
	# AT THE FIRST CONTERZONE (NUMBERING STARTS FROM 0)
	# $node[$countop][node_number][$type]
	# $node[$countop][node_number][$height]. # EXAMPLE: $node[0][3][$node]. THIS IS THE HEIGHT OF THE 3RD NODE AT THE FIRST COUNTERZONE
	# THEN IT MAKES AVAILABLE THE FOLLOWING VARIABLES REGARDING NODES:
	# $node[$countop][node_number][$volume] # REGARDING INTERNAL NODES
	# $node[$countop][node_number][$azimut] # REGARDING BOUNDARY NODES
	# THEN IT MAKE AVAILABLE THE FOLLOWING VARIABLES REGARDING COMPONENTS:
	# $node[$countop][node_number][$area] # REGARDING SIMPLE OPENINGS
	# $node[$countop][node_number][$width] # REGARDING CRACKS
	# $node[$countop][node_number][$length] # REGARDING CRACKS
	# $node[$countop][node_number][$door_width] # REGARDING DOORS
	# $node[$countop][node_number][$door_height] # REGARDING DOORS
	# $node[$countop][node_number][$door_nodeheight] # REGARDING DOORS
	# $node[$countop][node_number][$door_discharge] # REGARDING DOORS (DISCHARGE FACTOR)

	# ALSO, THIS KIND OF FILE MAKES INFORMATION AVAILABLE ABOUT 
	# THE MORPHING STEP OF THE MODELS AND THE STEPS THE MODEL HAVE TO FOLLOW.
	# THIS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO THESE VARIABLES, 
	# WHICH COULD ALSO BE COMBINED WITH THE FOLLOWING ONES: 
	# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
	# $countop, WHICH TELLS THE PROGRAM WHAT OPERATION IS BEING EXECUTED IN THE CHAIN OF OPERATIONS 
	# THAT MAY BE EXECUTES AT EACH MORPHING PHASE. EACH $countop WILL CONTAIN ONE OR MORE ITERATION STEPS.
	# TYPICALLY, IT WILL BE USED FOR A ZONE, BUT NOTHING PREVENTS THAT SEVERAL OF THEM CHAINED ONE AFTER 
	# THE OTHER ARE APPLIED TO THE SAME ZONE.
	# $countstep, WHICH TELLS THE PROGRAM WHAT THE CURRENT ITERATION STEP IS.
	# $countvar, WHICH TELLS THE PROGRAM WHAT NUMBER OF DESIGN PARAMETER THE PROGRAM IS WORKING AT.

	# The $countop that is actuated is always the last, the one which is active. 
	# Differentent $countops can be referred to the same zone. Different $countops just number mutations in series.
	# So referral to different time steps when needed has to be explicitly specified in the files in which the criteria
	# for propagation of constraints are written.

	my ( $to, $stepsvar, $countop, $countstep, $swap, $justread, $justwrite, $swap2, $countvar, $fileconfig ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @propagate_constraints = @$swap2;
	
	say "Propagating constraints on multiple databases " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $zone = $applytype[$countop][3];
	my $count = 0;
	my @group = @{$propagate_constraints[$countop]};
	foreach my $elm (@group)
	{
		if ($count > 0)
		{
			my @items = @{$elm};
			my $what_to_do = $items[0];
			my $sourcefile = $items[1];
			my $targetfile = $items[2];
			my $configfile = $items[3];
			my $askop = $items[6];
			if ($what_to_do eq "read_geo")
			{
				$to_do = "justread";
				my @vertex_letters = @{$items[4]};
				my $long_menus = $items[5];
				my @constrain_geometry = ( [ $zone,  $sourcefile, $targetfile, $configfile , \@vertex_letters, $long_menus ] );
				constrain_geometry( $to, $fileconfig, $stepsvar, $countop, $countstep, 
					$exeonfiles, \@applytype, \@constrain_geometry, $to_do, $countvar, $fileconfig );

			}
			elsif ($what_to_do eq "read_obs")
			{
				$to_do = "justread";
				my @obs_letters = @{$items[4]};
				my $act_on_materials = $items[5];
				my @constrain_obstructions = ( [ $applytype[$countop][3], $sourcefile, $targetfile, $configfile , \@obs_letters, $act_on_materials ] );
				constrain_obstructions( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_obstructions, $to_do, $countvar, $fileconfig );
			}
			elsif ($what_to_do eq "read_ctl")
			{
				$to_do = "justread";
				my @constrain_controls = ( [ $zone, $sourcefile, $targetfile, $configfile ] );
				constrain_controls( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_controls, $to_do, $countvar, $fileconfig  );
			}
			elsif ($what_to_do eq "read_net")
			{
				$to_do = "justread";
				my @surfaces = @{$items[4]};
				my @cps = @{$items[5]};
				my @constrain_net = ( [ $zone, $sourcefile, $targetfile, $configfile , \@surfaces, \@cps ] );
				constrain_net( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_net, $to_do, $countvar, $fileconfig  );
			}

			elsif ($what_to_do eq "write_geo")
			{
				$to_do = "justwrite";
				my @vertex_letters = @{$items[4]};
				my $long_menus = $items[5];
				my @constrain_geometry = ( [ $zone,  $sourcefile, $targetfile, $configfile , \@vertex_letters, $long_menus, $askop ] );
				constrain_geometry( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_geometry, $to_do, $countvar, $fileconfig );
			}
			elsif ($what_to_do eq "write_obs")
			{
				$to_do = "justwrite";
				my @obs_letters = @{$items[4]};
				my $act_on_materials = $items[5];
				my @constrain_obstructions = ( [ $zone, $sourcefile, $targetfile, $configfile , \@obs_letters, $act_on_materials] );
				constrain_obstructions( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_obstructions, $to_do, $countvar, $fileconfig  );
			}
			elsif ($what_to_do eq "write_ctl")
			{
				$to_do = "justwrite";
				my @constrain_controls = ( [ $zone, $sourcefile, $targetfile, $configfile ] );
				constrain_controls( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_controls, $to_do, $countvar, $fileconfig  );
			}
			elsif ($what_to_do eq "write_net")
			{
				$to_do = "justwrite";
				my @surfaces = @{$items[4]};
				my @cps = @{$items[5]};
				my @constrain_net = ( [ $zone, $sourcefile, $targetfile, $configfile , \@surfaces, \@cps ] );
				constrain_net( $to, $stepsvar, $countop, 
					$countstep, \@applytype, \@constrain_net, $to_do, $countvar, $fileconfig );
			}		
		}
		$count++;
	}
}
###########################################################################
# END OF SECTION DEDICATED TO GENERIC FUNCTIONS FOR PROPAGATING CONSTRAINTS

1;
