package Sim::OPT::Morph;
# Copyright (C) 2008-2015 by Gian Luca Brunetti and Politecnico di Milano.
# This is the module Sim::OPT::Morph of Sim::OPT.
# 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 Storable qw(dclone);
use File::Copy qw( move copy );
use Data::Dumper;
use Sim::OPT;
use Sim::OPT::Sim;
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;
#use diagnostics;
#use diagnostics -verbose;
#enable  diagnostics;
#disable diagnostics;
use warnings::unused;
@ISA = qw( Exporter ); 
#%EXPORT_TAGS = ( DEFAULT => [qw( &opt &prepare )]); # our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
#@EXPORT   = qw(); # our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw( 
morph translate translate_surfaces_simple translate_surfaces rotate_surface translate_vertices shift_vertices rotate 
rotatez make_generic_change reassign_construction change_thickness bring_obstructions_back 
recalculateish daylightcalc daylightcalc_other change_config checkfile change_climate recalculatenet apply_constraints 
reshape_windows warp use_modish export_toenergyplus genchange genprop change_groundreflectance 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 readobsfile obs_modify 
decreasearray deg2rad rad2deg purifyarray replace_nth rotate2dabs rotate2d rotate3dxyz fixlength purifydata
); # our @EXPORT = qw( );

$VERSION = '0.50.3'; # our $VERSION = '';

################################################# MORPH					

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); 
	my $configfile = %{ $dat{configfile} }; #say "dump(\$configfile): " . dump($configfile); 
		
	$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;
	$tofile = $main::tofile;
	$report = $main::report;
	$simnetwork = $main::simnetwork;
	
	$tee = new IO::Tee( \*STDOUT, ">>$tofile" ); # GLOBAL ZZZ
	
	#open( OUTFILE, ">>$outfile" ) or die "Can't open $outfile: $!"; 
	open( TOFILE, ">>$tofile" ) or die "Can't open $tofile: $!"; 
	say $tee "\n# Now in Sim::OPT::Morph.\n";
	
	%dowhat = %main::dowhat; #say $tee "dumpINMORPH(\%dowhat): " . ( %dowhat );
	
	%simtitles = %main::simtitles; #say $tee "dumpINMORPH(\@simtitles): " . dump(@simtitles);
	%retrievedata = %main::retrievedata;
	@keepcolumns = @main::keepcolumns;
	@weights = @main::weights;
	@weightsaim = @main::weightsaim;
	@varthemes_report = @main::varthemes_report;
	@varthemes_variations = @main::varthemes_variations;
	@varthemes_steps = @main::varthemes_steps;
	@rankdata = @main::rankdata; # CUT ZZZ
	@rankcolumn = @main::rankcolumn;
	%reportdata = %main::reportdata;
	@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;
	%vals = %main::vals;
	
	require $configfile;
	
	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 $skipfile = $vals{skipfile}; #say $tee "dump(\$skipfile): " . dump($skipfile);
	my $skipsim = $vals{skipsim}; #say $tee "dump(\$skipsim): " . dump($skipsim);
	my $skipreport = $vals{skipreport}; #say $tee "dump(\$skipreport): " . dump($skipreport);
	
	if ( not ( $exeonfiles ) ) { $exeonfiles = "y"; }
	if ( not ( $preventsim ) ) { $preventsim = "n"; }
	if ( not ( $report ) ) { $report = "$mypath/$file-report.txt"; }
	
	#my $getpars = shift;
	#eval( $getpars );

	#if ( fileno (MORPHLIST) 
	
	
	#say $tee "dump(\@instances): " . dump(@instances);
	my $numberof_morphings = scalar ( keys %{ $dowhat{simtools} } ); #say $tee "\$numberof_morphings " . dump( $numberof_morphings );
	
	$countinstance = 1;
	foreach my $instance ( @instances )
	{	
		#say "ARRIVED1"; say TOFILE "ARRIVED1";
		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 $countmorphing = 1;
		my $numberof_morphings = scalar ( keys %{ $dowhat{simtools} } ); #say $tee "\$numberof_morphings " . dump( $numberof_morphings );
		#say $tee "\$countvar " . dump( $countvar );
		while ( $countmorphing <= $numberof_morphings )
		{	
			if ( not (defined ( $vals{$countmorphing}{$countvar}{general_variables} ) ) ) 
			{ 
				$vals{$countmorphing}{$countvar}{general_variables} = 
								[
								"y", # $generate(n) eq "n" # (if the models deriving from this runs will not be generating new models) or y (if they will be generating new models).
								"n" #if $sequencer eq "y", or "last" (of a sequence) iteration between non-continuous cases wanted.  The first gets appended to the middle(s) and to he last. Otherwise, "n".
								];
			}
			my @applytype = @{ $vals{$countmorphing}{$countvar}{applytype} }; #say $tee "dump(\@applytype): " . dump(@applytype);
			my $general_variables = $vals{$countmorphing}{$countvar}{general_variables}; #say "dump(\$general_variables): " . dump($general_variables);
			my @generic_change = @{$vals{$countmorphing}{$countvar}{generic_change} }; 
			my $rotate = $vals{$countmorphing}{$countvar}{rotate}; 
			my $rotatez = $vals{$countmorphing}{$countvar}{rotatez};
			my $translate = $vals{$countmorphing}{$countvar}{translate}; #say $tee "dump(\$translate): " . dump($translate); 
			my $translate_surface = $vals{$countmorphing}{$countvar}{translate_surface};
			my $keep_obstructions = $vals{$countmorphing}{$countvar}{keep_obstructions};
			my $shift_vertices = $vals{$countmorphing}{$countvar}{shift_vertices};
			my $construction_reassignment = $vals{$countmorphing}{$countvar}{construction_reassignment};
			my $change_thickness = $vals{$countmorphing}{$countvar}{change_thickness};
			my $recalculateish = $vals{$countmorphing}{$countvar}{recalculateish};
			my @recalculatenet = @{ $vals{$countmorphing}{$countvar}{recalculatenet} };
			my $obs_modify = $vals{$countmorphing}{$countvar}{obs_modify}; #say $tee "dump(\$obs_modify): " . dump($obs_modify); 
			my $netcomponentchange = $vals{$countmorphing}{$countvar}{netcomponentchange};
			my $changecontrol = $vals{$countmorphing}{$countvar}{changecontrol};
			my @apply_constraints = @{ $vals{$countmorphing}{$countvar}{apply_constraints} };
			my $rotate_surface = $vals{$countmorphing}{$countvar}{rotate_surface};
			my @reshape_windows = @{ $vals{$countmorphing}{$countvar}{reshape_windows} };
			my @apply_netconstraints = @{ $vals{$countmorphing}{$countvar}{apply_netconstraints} };
			my @apply_windowconstraints = @{ $vals{$countmorphing}{$countvar}{apply_windowconstraints} };
			my @translate_vertices = @{ $vals{$countmorphing}{$countvar}{translate_vertices} };
			my $warp = $vals{$countmorphing}{$countvar}{warp};
			my @daylightcalc = @{ $vals{$countmorphing}{$countvar}{daylightcalc} };
			my @change_config = @{ $vals{$countmorphing}{$countvar}{change_config} };
			my @constrain_geometry = @{ $vals{$countmorphing}{$countvar}{constrain_geometry} }; #say $tee "dump(\@constrain_geometry): " . dump(@constrain_geometry); 
			my @vary_controls = @{ $vals{$countmorphing}{$countvar}{vary_controls} };
			my @constrain_controls =  @{ $vals{$countmorphing}{$countvar}{constrain_controls} };
			my @constrain_obstructions = @{ $vals{$countmorphing}{$countvar}{constrain_obstructions} };
			my @get_obstructions = @{ $vals{$countmorphing}{$countvar}{get_obstructions} };
			my $checkfile = $vals{$countmorphing}{$countvar}{checkfile};
			my @vary_net = @{ $vals{$countmorphing}{$countvar}{vary_net} };
			my @constrain_net = @{ $vals{$countmorphing}{$countvar}{constrain_net} };
			my @propagate_constraints = @{ $vals{$countmorphing}{$countvar}{propagate_constraints} };
			my @change_climate = @{ $vals{$countmorphing}{$countvar}{change_climate} };
			my $pin_obstructions = $vals{$countmorphing}{$countvar}{pin_obstructions};
			my $constrain = $vals{$countmorphing}{$countvar}{constrain};
			my $use_modish = $vals{$countmorphing}{$countvar}{use_modish};
			my $export_toradiance = $vals{$countmorphing}{$countvar}{export_toradiance};
			my $genchange = $vals{$countmorphing}{$countvar}{genchange};
			my $genprop = $vals{$countmorphing}{$countvar}{genprop};
			my $change_groundreflectance = $vals{$countmorphing}{$countvar}{change_groundreflectance};
			my $export_toenergyplus = $vals{$countmorphing}{$countvar}{export_toenergyplus}; 
			my $skipop = $vals{$countmorphing}{$countvar}{skipop}; #say TOFILE "dumpinmorph(\$skipop): " . dump($skipop);
			
			my ( @cases_to_sim, @files_to_convert );
			my ( @obs, @node, @component, @loopcontrol, @flowcontrol, @new_loopcontrol, @new_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, @v_, @obs_, @donode, @docomponent, @doloopcontrol, @doflowcontrol); # THINGS LOCAL AS REGARDS TO COUNTER ZONE CYCLES
			my ( %names, %newcontents, @filecontents, @newfilecontents );
			
			my $generate  = $$general_variables[0];
			my $sequencer = $$general_variables[1];
			my $dffile = "df-$file.txt";
			
			#my $tofilemorph = "$tofile" . "-1morph.txt";
			#my $outfilemorph = "$outfile" . "-1morph.txt";
			
			#open( TOFILE, ">>$tofilemorph" );
			#open( OUTFILE, ">>$outfilemorph" );
		
					
			#say $tee "\$dowhat{actonexisting_models}->{\$countmorphing }" . dump( $dowhat{actonexisting_models}->{$countmorphing} );
			#say $tee "\$dowhat{numberof_morphings} " . dump( $dowhat{numberof_morphings} );
			if ( ( $countblock == 0 ) and ( $countstep == 1 ) )
			{
				if (not ( -e "$origin" ) )
				{
					unless ($exeonfiles eq "n") 
					{ 
						unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
						{
							`cp -R $mypath/$file $from`; #say "FROM: $from";
						}
						else
						{
							`xcopy  /e /c /r /y $mypath\\$file $from`; #say "FROM: $from";
						}
					}
					unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
					{
						say TOFILE "cp -R $mypath/$file $from\n";
					}
					else
					{
						say TOFILE "xcopy  /e /c /r /y $mypath\\$file $from\n";
					}
				}
			}
			
			#if ( fileno (RETLIST) )
			#if (not (-e $morphlist ) )
			#{
			#	if ( $countblock == 0 )
			#	{
					open( MORPHLIST, ">>$morphlist") or die( "$!" ); # or die;
			#	}
			#	else 
			#	{
			#		open( MORPHLIST, ">>$morphlist") or die;
			#	}
			#}
			
			#if ( fileno (MORPHBLOCK) )
			#if (not (-e $morphblock ) )
			#{
			#	if ( $countblock == 0 )
			#	{
					open(MORPHBLOCK, ">>$morphblock") or die( "$!" );# or die;
			#	}
			#	else
			#	{
			#		open(MORPHBLOCK, ">>$morphblock");# or die;
			#	}		
			#}	
			#if ( ( $to eq $origin ) or ( not ( eval ( $skip) ) ) )
			#if  ( not ( eval ( $skip) ) )
			#{
				push ( @{ $morphstruct[$countcase][$countblock] }, $to );
				print MORPHBLOCK "$to\n";
			#}
			#say "ARRIVED2"; say TOFILE "ARRIVED2";
			
			#if ( ( not ( $to ~~ @morphcases ) ) and ( ( $to eq $origin ) or ( not ( eval ( $skip) ) ) ) )
			#if ( ( ( ( $to eq $origin ) or ( not ( $to ~~ @morphcases ) ) ) ) and ( ( $to eq $origin ) or ( not ( eval ( $skip) ) ) ) )
			if ( not ( $to ~~ @morphcases ) )
			#if  ( not ( eval ( $skip) ) ) 
			{
				#say "HERE2. MORPHCASES.";
				push ( @morphcases, $to );
				print MORPHLIST "$to\n";
				say $tee "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 )
				#		{
				#			unless ($exeonfiles eq "n") { print `chmod -R 777 $from\n`; }
				#			print TOFILE "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 )
				#		#{
				#		#	unless ($exeonfiles eq "n") { print `chmod -R 777 $from\n`; }
				#		#	print TOFILE "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";
				#}
				#say "ARRIVED3"; say TOFILE "ARRIVED3";	
				
						
				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 ) ) or ( $dowhat{overwrite_models}->{$countmorphing} eq "y" ) )
				#)
				{
					#say TOFILE "HERE2A. MAIN. ";
					#say "ARRIVED4"; say TOFILE "ARRIVED4";
					unless ($exeonfiles eq "n") 
					{ 
						unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
						{
							`cp -R $origin $to\n`; 
						}
						else
						{
							`xcopy  /e /c /r /y $origin $to\n`; 
						}
					}
					unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
					{
						print TOFILE "cp -R $origin $to\n\n";
					}
					else
					{
						print TOFILE "xcopy  /e /c /r /y $origin $to\n\n";
					}
					#say "HERE2B";
					#}
					
					my $passmorph;
					#say $tee "HERE \$dowhat{actonexisting_models}->{\$countmorphing } " . dump( $dowhat{actonexisting_models}->{ $countmorphing } );
					if ( $dowhat{actonexisting_models}->{$countmorphing} eq "y" )
					{
						$passmorph = "pass";
					}
					
					( $passmorph ) ? ( eval( $evalthis ) ) : ( "nothing" );
				}
				
				if ( ( $dowhat{actonexisting_models}->{$countmorphing} eq "y" ) )
				{	
					#if ( $passmorph eq "pass" )
					#{
					#	eval( $evalthis ); say TOFILE "EVALED";
					#}
					
					# $passmorph ? eval( $evalthis ) : " " ;		
					
					#{				
					my $countop = 0; # "$countop" IS THE COUNTER OF THE OPERATIONS
					foreach my $op (@applytype) # "$op" MEANS OPERATION
					{
						#say "ARRIVED5"; say TOFILE "ARRIVED5";
						my $skip = $skipop->[ $countop ];
						my $modification_type = $applytype[$countop][0];
						say $tee "\$modification_type: $modification_type; \$countop: $countop"; say $tee "\$modification_type: $modification_type; \$countop: $countop"; 
						if ( ( $applytype[$countop][1] ne $applytype[$countop][2] ) and ( $modification_type ne "changeconfig" ) )
						{
							unless ($exeonfiles eq "n") 
							{  
								unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
								{
									`cp -f $to/zones/$applytype[$countop][1] $to/zones/$applytype[$countop][2]\n`; 
								}
								else
								{
									`xcopy  /e /c /r /y $to\\zones\\$applytype[$countop][1] $to\\zones\\$applytype[$countop][2]\n`; 
								}
							}
							unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
							{
								print TOFILE "cp -f $to/zones/$applytype[$countop][1] $to/zones/$applytype[$countop][2]\n\n";
							}
							else
							{
								print TOFILE "xcopy /e /c /r /y $to\\zones\\$applytype[$countop][1] $to\\zones\\$applytype[$countop][2]\n\n";
							}
							unless ($exeonfiles eq "n") 
							{  
								unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
								{
									`cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n`; 
								}
								else
								{
									`xcopy /e /c /r /y $to\\cfg\\$applytype[$countop][1] $to\\cfg\\$applytype[$countop][2]\n`; 
								}
							}    # ORDINARILY, THIS PART CAN BE REMOVED
							unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
							{
								print TOFILE "cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n"; 
							}
							else
							{
								print TOFILE "xcopy /e /c /r /y $to\\cfg\\$applytype[$countop][1] $to\\cfg\\$applytype[$countop][2]\n"; 
							}
						}
						if ( ( $applytype[$countop][1] ne $applytype[$countop][2] ) and ( $modification_type eq "changeconfig" ) )
						{
							unless ($exeonfiles eq "n") 
							{ 
								unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
								{
									`cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n`; 
								}
								else
								{
									`xcopy /e /c /r /y $to\\cfg\\$applytype[$countop][1] $to\\cfg\\$applytype[$countop][2]\n`; 
								}
							}
							unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
							{
								print TOFILE "cp -f $to/cfg/$applytype[$countop][1] $to/cfg/$applytype[$countop][2]\n"; 
							}
							else
							{
								print TOFILE "xcopy /e /c /r /y $to\\cfg\\$applytype[$countop][1] $to\\cfg\\$applytype[$countop][2]\n"; 
							}
						} # ORDINARILY, THIS PART CAN BE REMOVED

						
						print `cd $to`;
						print TOFILE "cd $to\n\n";
						
						my $launchline;
						unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
						{
							$launchline = " -file $to/cfg/$fileconfig -mode script";
						}
						else
						{
							$launchline = " -file $to\\cfg\\$fileconfig -mode script";
						}
						say TOFILE "AFTER DEFINITION \$launchline : $launchline" ;
						#if ( ( $stepsvar > 1) and ( not ( eval $skip) ) )
						if ( ( $stepsvar > 1) and ( not ( eval ( $skip ) ) ) )
						{	
							#say "ARRIVED6"; say TOFILE "ARRIVED6";
							#say "\$modification_type: $modification_type; \$countop: $countop"; say TOFILE "\$modification_type: $modification_type; \$countop: $countop"; 

							sub dothings
							{	say TOFILE "IN DOTHINGS \$launchline : $launchline" ;
								#say TOFILE "CALLED DOTHINGS";
								my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, 
								$exeonfiles, $to_do, $launchline  ) = @_;
								my @applytype = @$applytype_ref;
								my @propoperations = @$to_do;
								
								foreach my $propop ( @propoperations )
								{
									if ( ( defined( $constrain_geometry[$countop] ) ) and ( ( $propop eq "read_geo" ) or ( $propop eq "write_geo" ) ) )
									{ 
										#say TOFILE "HERE I AM";
										my ( $v_ref ) = constrain_geometry
										( $to, $stepsvar, $countop, 
											$countstep, \@applytype, \@constrain_geometry, $countvar, $fileconfig, \@v_, $countmorphing, $exeonfiles, \@v_, $propop, $launchline ); 
										@v = @$v_ref;
										@v_ = @$v__ref;
									}
									if ( ( defined( $genprop[$countop] ) ) and ( ( $propop eq "read_gen" ) or ( $propop eq "write_gen" ) ) )
									{ 
										( $names_ref, $newcontents_ref, $filecontents_ref, $newfilecontents_ref ) = 
											genprop ( $to, $stepsvar, $countop, $countstep,
												\@applytype, $genchange, $countvar, $fileconfig, $mypath, $file, $countmorphing, $propop,  
												$names_ref, $nums_ref, $newcontents_ref, $filecontents_ref, 
												$newfilecontents_ref, $launchline );
												%nums = %$nums_ref;
												%names = %$names_ref;
												%newcontents = %$newcontents_ref;
												@filecontents = @$filecontents_ref;
												@newfilecontents = @$newfilecontents_ref;
									}
									if ( $pin_obstructions->[ $countop ] )
									{ 	
										pin_obstructions
										( $to, $stepsvar, $countop, 
											$countstep, \@applytype, $pin_obstructions, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ); 
									}
									if ( ( defined ( $constrain_obstructions[$countop] ) ) and ( ( $propop eq "read_obs" ) or ( $propop eq "write_obs" ) ) )
									{ 	#say TOFILE "HIT"; 
										my ( $obs_ref, $obs__ref ) = constrain_obstructions
										( $to, $stepsvar, $countop, 
											$countstep, \@applytype, \@constrain_obstructions, $countvar, $fileconfig, $countmorphing, $exeonfiles, $obs_ref, $obs__ref, $propop, $launchline ); 
											@obs = @$obs_ref;
											@obs_ = @$obs__ref;
									}
									if ( ( defined( $constrain_net[$countop] ) ) and ( ( $propop eq "read_net" ) or ( $propop eq "write_net" ) ) )
									{ 
										my ( $node_ref, $component_ref, $donode_ref, $docomponent_ref ) = constrain_net( $to, $stepsvar, $countop, 
											$countstep, \@applytype, \@constrain_net, $countvar, $fileconfig, $countmorphing, $exeonfiles, $propop,
											$node_ref, $component_ref, $donode_ref, $docomponent_ref, $launchline ); 
											@node = @$node_ref;
											@component = @$component_ref;
											@donode = @$donode_ref;
											@docomponent = @$docomponent_ref;
									}
									if ( ( defined( $constrain_controls[$countop] ) ) and ( ( $propop eq "read_ctl" ) or ( $propop eq "write_ctl" ) ) )
									{ 
										my ( $loopcontrol_ref, $flowcontrol_ref, $new_loopcontrol_ref, $new_flowcontrol_ref ) = constrain_controls
										( $to, $stepsvar, $countop, 
											$countstep, \@applytype, \@constrain_controls, $countvar, $fileconfig, $countmorphing, $exeonfiles, $propop, 
											$loopcontrol_ref, $flowcontrol_ref, $new_loopcontrol_ref, $new_flowcontrol_ref, $launchline  ); 
											@loopcontrol = @$loopcontrol_ref;
											@flowcontrol = @$flowcontrol_ref;
											@new_loopcontrol = @$new_loopcontrol_ref;
											@new_flowcontrol = @$new_flowcontrol_ref;
									}
								}
								
								if ( $pin_obstructions->[ $countop ] )
								{ 	
									pin_obstructions
									( $to, $stepsvar, $countop, 
										$countstep, \@applytype, $pin_obstructions, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  ); 
								}
								if ( $$keep_obstructions[$countop] ) 
								{ 
									&bring_obstructions_back( $to, $stepsvar, $countop, 
										$countstep, \@applytype, $keep_obstructions, $countvar, $fileconfig, $countmorphing, $launchline  ); 
								}
								if ( $apply_constraints[$countop] ) 
								{ 
									&apply_constraints
									( $to, $stepsvar, $countop, 
										$countstep, \@applytype, \@apply_constraints, $countvar, $fileconfig, $countmorphing, $launchline  ); 
								}
								if ( $recalculatenet[$countop]  ) 
								{ 
									&recalculatenet
									( $to, $stepsvar, $countop, 
										$countstep, \@applytype, \@recalculatenet, $countvar, $fileconfig, $countmorphing, $launchline  ); 
								}
								if ( $recalculateish->[$countop] ) 
								{ 	#say TOFILE "IN USE RECALCULATEISH \$launchline : $launchline" ;
									&recalculateish
									( $to, $stepsvar, $countop, 
										$countstep, \@applytype, $recalculateish, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  ); 
								}
								if ( $daylightcalc->[$countop] ) 
								{ 	
									&daylightcalc
									( $to, $stepsvar, $countop,  
										$countstep, \@applytype, $filedf, \@daylightcalc, $countvar, $fileconfig, $countmorphing, $launchline  ); 
								}
								if ( $use_modish->[$countop]  ) 
								{ 	
									&use_modish
									( $to, $stepsvar, $countop, 
										$countstep, \@applytype, $use_modish, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ); 
								}
								if ( $export_toenergyplus->[$countop]  ) 
								{ 
									#say TOFILE "ENTERED";
									export_toenergyplus
									( $to, $stepsvar, $countop, 
										$countstep, \@applytype, $export_toenergyplus, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  ); 
								}
							} # END SUB DOTHINGS
							my $to_do = $propagate_constraints[ $countop ];
							if ( $modification_type eq "change_groundreflectance" )#
							{
								#say TOFILE "HERE GROUND";
								change_groundreflectance
								( $to, $stepsvar, $countop, $countstep,
									\@applytype, $change_groundreflectance, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline   );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "genchange" )#
							{
								( $names_ref, $nums_ref, $newcontents_ref, $filecontents_ref, $newfilecontents_ref ) = genchange
								( $to, $stepsvar, $countop, $countstep,
									\@applytype, $genchange, $countvar, $fileconfig, $mypath, $file, 
									$countmorphing, "vary", $names_ref, $nums_ref, 
									$newcontents_ref, $filecontents_ref, $newfilecontents_ref, $launchline );
								%names = %$names_ref;
								%nums = %$nums_ref;
								%newcontents = %$newcontents_ref;
								#@filecontents = @$filecontents_ref;
								@newfilecontents = @$newfilecontents_ref;
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, 
								$mypath, $file, $countmorphing, $to_do, $launchline, $propop  );
							} #
							elsif ( $modification_type eq "generic_change" )#
							{
								make_generic_change
								( $to, $stepsvar, $countop, $countstep,
									\@applytype, $generic_change, $countvar, $fileconfig, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} #
							elsif ( $modification_type eq "translate_surface" )
							{
								translate_surfaces 
								($to, $stepsvar, $countop, $countstep, 
									\@applytype, $translate_surface, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline   );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "rotate_surface" )              #
							{
								rotate_surface
								($to, $stepsvar, $countop, $countstep, 
									\@applytype, $rotate_surface, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "shift_vertices" )
							{
								shift_vertices
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $shift_vertices, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "translate_vertices" )
							{
								translate_vertices
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, \@translate_vertices, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );                         
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}  
							elsif ( $modification_type eq "construction_reassign" )
							{
								reassign_construction
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $construction_reassign, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "rotate" )
							{
								rotate
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $rotate, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "translate" )
							{
								#say $tee "GOING TO TRANSLATE";
								translate
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $translate, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "change_thickness" )
							{
								change_thickness
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $change_thickness, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "rotatez" )
							{
								rotatez
								($to, $stepsvar, $countop, $countstep, 
									\@applytype, $rotatez, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( $modification_type eq "change_config" )
							{
								change_config
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, \@change_config, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "reshape_windows" ) 
							{
								reshape_windows
								($to, $stepsvar, $countop, $countstep, 
									\@applytype, \@reshape_windows, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline );					
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "obs_modify" ) 
							{	#say $tee "LAUNCHING7";
								obs_modify
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $obs_modify, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								#say $tee "CALLING DOTHINGS";
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "warping" )
							{
								warp
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, $warp, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "vary_controls" )
							{
								vary_controls
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, \@vary_controls, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "vary_net" )
							{
								vary_net
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, \@vary_net, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do, $launchline  );
							}
							elsif ( $modification_type eq "change_climate" )
							{
								change_climate
								( $to, $stepsvar, $countop, $countstep, 
									\@applytype, \@change_climate, $countvar, $fileconfig, $mypath, $file, $countmorphing, $countmorphing, $launchline  );
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, $countmorphing, $to_do, $launchline  );
							} 
							elsif ( ( $modification_type eq "constrain_controls" ) or ( $modification_type eq "constrain_geometry" ) or ( $modification_type eq "constrain_net" ) or
								( $modification_type eq "constrain_obstructions" ) or ( $modification_type eq "genprop" ) )
							{	say TOFILE "IN CALL DOTHINGS \$launchline : $launchline" ;
								dothings ( $to, $stepsvar, $countop, $countstep, \@applytype, $countvar, $fileconfig, $mypath, $file, $countmorphing, 
								$exeonfiles, $to_do, $launchline ) ;
							}
							else 
							{ 
								say "Can't recognize the modification type. So quitting.";
								die( "$!" );
							}
						}
						$countop++;
						print `cd $mypath`;
						print TOFILE "cd $mypath\n\n";
					}
				}
				#else
				#{
				#	unless ($exeonfiles eq "n") { print `cp -R $origin $to\n`; }
				#	print TOFILE "cp -R $origin $to\n\n";
				#}
				#push(@morphed, $to);
			}
			$countmorphing++;
		}
		close MORPHLIST;
		close MORPHBLOCK;
		$countinstance++;
	}
	close TOFILE;
	close OUTFILE;
	return (\@morphcases, \@morphsruct);
}    # END SUB morph


############################################ GENERAL FUNCTIONS


sub decreasearray
{
	my @arr = @_;
	my @newarr;
	foreach ( @arr )
	{
		push ( @newarr, ( $_ - 1 ) );
	} # say TOFILE "\@newarr " . dump( @newarr );
	return ( @newarr );
}

sub deg2rad 
{
	my $degrees = shift;
	return ( ( $degrees / 180 ) * 3.14159265358979 );
}

sub rad2deg 
{
	my $radians = shift;
	return ( ( $radians / 3.14159265358979 ) * 180 );
}
    
    
sub purifyarray
{
	my @elts = @_;
	my @cleanarr;
	foreach my $elt ( @elts )
	{
		if ( not ( $elt eq "" ) )
		{
			push ( @cleanarr, $elt );
		}
	}
	return ( @cleanarr );
}

sub replace_nth
{
	my ( $row, $position, $string, $newstring ) = @_; 
	$row =~ s/((?:$string.*?){$position})$string/${1}$newstring/; 
	return ( $row ); 
}

sub rotate2dabs # CHECK! ZZZ
{
    my ( $x, $y, $angle ) = @_;
    $angle = deg2rad( $angle );
    my $x_new = cos($angle)*$x - sin($angle)*$y;
    my $y_new = sin($angle)*$x + cos($angle)*$y;
  return ( $x_new, $y_new);
}

sub rotate2d {
    my ( $x, $y, $angle, $centrex, $centrey ) = @_;
    $angle = deg2rad( $angle );
    my $tempx = ( $x - $centrex );
    my $tempy = ( $y - $centrey );
    my $x_temp_new = cos($angle)*$tempx - sin($angle)*$tempy;
    my $y_temp_new = sin($angle)*$tempx + cos($angle)*$tempy;
    my $x_new = ( $x_temp_new + $centrex );
    my $y_new = ( $y_temp_new + $centrey );
  return ( $x_new, $y_new);
}

sub rotate3dxyz # CHECK! ZZZ
{
	my ( $vertices_ref, $angle, $centre_ref, $plantype ) = @_;
	my @vertices = @$vertices_ref;
	my @centreverts = @$centre_ref;
	my ( $centre_x, $centre_y, $centre_z ) = $centreverts[0], $centreverts[1], $centreverts[2];
	my @newbag;
	
	foreach $vertex_ref ( @vertices )
	{
		( $x, $y, $z ) = ( $vertex_ref->[0], $vertex_ref->[1], $vertex_ref->[2]);
		if ( $plantype eq "xy" )
		{
			my ( $newx, $newy ) = rotate2d( $x, $y, $angle, $centre_x, $centre_y );
			push ( @newbag, [ $newx, $newy, $z ] );
		}
		elsif ( $plantype eq "xz" )
		{
			my ( $newx, $newz ) = rotate2d( $x, $z, $angle, $centre_x, $centre_z );
			push ( @newbag, [ $newx, $y, $newz ] );
		}
		elsif ( $plantype eq "yz" )
		{
			my ( $newy, $newz ) = rotate2d( $y, $z, $angle, $centre_y, $centre_z );
			push ( @newbag, [ $x, $newy, $newz ] );
		}
	return ( @newbag );
	}
}

sub fixlength 
{
	my ( $el, $newel, $adjustanswer ) = @_; #say "\$newel !: " . dump( $newel ); 
	#say TOFILE "ENTERING: \$el: $el, \$newel: $newel ";
	my $length = length( $el ); #say "\$length !: " . dump( $length ); 
	
	my $truenewel;
	if ( ( $el < 0 ) and ( $adjustanswer eq "y" ) )
	{
		if ( not ( $el =~ /\./ ) )
		{
			
			my $thisel = "$el" . ".000";
		}
		else
		{
			$truenewel = substr( $newel, 0, $length ); #say "\$truenewel !: " . dump( $truenewel ); 
		}
	}
	elsif ( ( $el >= 0 ) and ( $newel < 0 ) and ( $adjustanswer eq "y" ) )
	{
		my $adjustedlengt;
		if ( not ( $el =~ /\./ ) )
		{
			my $thisel = "$el" . ".000";
			$adjustedlength = length( $thisel ); #ay "\$length !: " . dump( $length );
			$truenewel = substr( $newel, 0, $adjustedlength); #say "\$truenewel !: " . dump( $truenewel ); 
		}
		$truenewel = " " . "$truenewel";
	}
	elsif ( ( $el >= 0 ) and ( $newel < 0 ) and ( $adjustanswer eq "y" ) )
	{
		if ( $el =~ /\./ )
		{
			my $thisel = "$el" . "000";
			$adjustedlength = length( $thisel ); say "\$length !: " . dump( $length );
			$truenewel = substr( $newel, 0, $adjustedlength); #say "\$truenewel !: " . dump( $truenewel ); 
		}
	}
	elsif ( ( $el >= 0 ) and ( $newel >= 0 ) and ( $adjustanswer eq "y" ) )
	{
		my $adjustedlength ;
		if ( not ( $el =~ /\./ ) )
		{
			my $thisel = "$el" . ".000";
			$adjustedlength = length( $thisel ); #say "\$length !: " . dump( $length );
			$truenewel = substr( $newel, 0, $adjustedlength); #say "\$truenewel !: " . dump( $truenewel ); 
		}
		$truenewel = " " . "$truenewel";
	}
	
	$truenewel = sprintf( "%.3f", $truenewel ); 
	
	if ( ( $el >= 0 ) and ( $newel => 0 ) and ( $adjustanswer eq "n" ) )
	{
		if ( $el =~ /\./ )
		{
			$newel = $newel . "000";  #say "\$newel !: " . dump( $newel ); 
		}	
		$truenewel = substr( $newel, 0, $length); #say "\$truenewel !: " . dump( $truenewel ); 
	}
	#say TOFILE " RETURNING \$el !: " . dump( $el ) . "RETURNING \$truenewel !: " . dump( $truenewel );
	return ( "$el", "$truenewel" ); 
}

sub purifydata
{	# IT BRINGS ALL THE NUMBERS IN A LIST OF LIST (LIKE: VERTEXES) IN A FILE AT THE SAME LENGTH OF ANOTHER SPECIFIED LIST
	my ( $modelarr_ref, $newarr_ref ) = @_;
	@modelarr = @$modelarr_ref;  #say $tee "\SENT \@modelarr : " . dump ( @modelarr );
	@newarr = @$newarr_ref; #say $tee "\SENT \@newarr : " . dump ( @newarr );
	
	my $countout = 0;
	foreach my $row ( @modelarr )
	{ 	#say $tee "INPURIFY \$row : " . dump ( $row );
		my $rownew = $newarr[ $countout ]; #say $tee "\$rownew : " . dump ( $rownew );
		my $countin = 0;
		foreach my $elt ( @$row )
		{ 	#say $tee "\$elt0 : " . dump ( $elt );
			my $newelt = $rownew->[ $countin ] ; #say $tee "\$newelt0 : " . dump ( $newelt );
			if ( ( $newelt ne $elt ) or ( $newelt =! $elt ) )
			{ 	#say $tee "\$elt1 : " . dump ( $elt ); say $tee "\$newelt1 : " . dump ( $newelt );
				$newarr_ref->[ $countout ][ $countin ] = fixlength( "$elt", "$newelt" ); #say $tee "RETURNED $newarr_ref[ $countout ][ $countin ] : " . dump ( $newarr_ref[ $countout ][ $countin ] );
			}
			$countin++;
		}
		$countout++;
	} #say $tee "\$newarr_ref : " . dump ( $newarr_ref );
	return( $newarr_ref );
}

############################################ END OF GENERAL FUNCTIONS	


sub translate
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $translate, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	
	say $tee "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]"; #say  $tee "IN TRASL\@coord1 : " . dump( @coord1 );
		my $yes_or_no_update_radiation =  $$translate[$countop][1]; #say  $tee "IN TRASL\@coord1 : " . dump( @coord1 );
		my $configfile =  $$translate[$countop][3]; #say  $tee "IN TRASL\@coord1 : " . dump( @coord1 );
		
		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_begin, $y_begin, $z_begin, $x_end, $y_end, $z_end, $x_swing, $y_swing, $z_swing, $x_value, $y_value, $z_value );
		my ( @coord2, @coord1 );
			
		if ( ref( $coordinates_for_movement[0] ) )
		{
			@coord1 = @{ $coordinates_for_movement[0] }; #say  TOFILE "\@coord1 : " . dump( @coord1 );
			@coord2 = @{ $coordinates_for_movement[1] }; #say TOFILE  "\@coord2 : " . dump( @coord2 );
			( $x_begin, $y_begin, $z_begin ) = @coord1; #say TOFILE  "\$x_begin : " . dump( $x_begin ); say TOFILE  "\$y_begin : " . dump( $y_begin ); say TOFILE  "\$z_begin : " . dump( $z_begin );
			( $x_end, $y_end, $z_end ) = @coord2; #say TOFILE  "\$x_end : " . dump( $x_end );say TOFILE  "\$y_end : " . dump( $y_end );say TOFILE  "\$z_end : " . dump( $z_end );
			
			$x_swing = ( $x_end - $x_begin ); #say TOFILE  "\$x_swing : " . dump( $x_swing );
			$y_swing = ( $y_end - $y_begin ); #say TOFILE  "\$y_swing : " . dump( $y_swing );
			$z_swing = ( $z_end - $z_begin ); #say TOFILE  "\$z_swing : " . dump( $z_swing );
			
			$x_pace = ( $x_swing / ( $stepsvar - 1 ) ); #say TOFILE  "\$x_pace : " . dump( $x_pace );
			$y_pace = ( $y_swing / ( $stepsvar - 1 ) ); #say TOFILE  "\$y_pace : " . dump( $y_pace );
			$z_pace = ( $z_swing / ( $stepsvar - 1 ) ); #say TOFILE  "\$z_pace : " . dump( $z_pace );
			
			$x_value = ( $x_begin + ( $x_pace * ( $countstep - 1) ) ); #say TOFILE  "\$x_value : " . dump( $x_value );
			$y_value = ( $y_begin + ( $y_pace * ( $countstep - 1) ) ); #say TOFILE  "\$y_value : " . dump( $y_value );
			$z_value = ( $z_begin + ( $z_pace * ( $countstep - 1) ) ); #say TOFILE  "\$z_value : " . dump( $z_value );
			#say TOFILE "COUNTSTEP - 1 = ( $countstep - 1 )";
		}
		else
		{
			$x_end = $coordinates_for_movement[0]; #say  "\$x_end : " . dump( $x_end );
			$x_swing = ( 2 * $x_end ); #say  "\$x_swing : " . dump( $x_swing );
			$x_base = $base[0]; #say  "\$x_base : " . dump( $x_base );
			
			$y_end = $coordinates_for_movement[1]; #say  "\$y_end : " . dump( $y_end );
			$y_swing = ( 2 * $y_end ); #say  "\$y_swing : " . dump( $y_swing );
			$y_base = $base[1]; #say  "\$y_base : " . dump( $y_base );
			
			$z_end = $coordinates_for_movement[2]; #say  "\$z_end : " . dump( $z_end );
			$z_swing = ( 2 * $z_end ); #say  "\$z_swing : " . dump( $z_swing );
			$z_base = $base[2]; #say  "\$z_base : " . dump( $z_base );

			$x_pace = ( $x_swing / ( $stepsvar - 1 ) ); #say  "\$x_pace : " . dump( $x_pace );
			$x_value = ($x_base + ( $x_end - ( $x_pace * ( $countstep - 1 ) ) )); #say  "\$x_value : " . dump( $x_value );
			$y_pace = ( $y_swing / ( $stepsvar - 1 ) ); #say  "\$y_pace : " . dump( $y_pace );
			$y_value = ($y_base + ( $y_end - ( $y_pace * ( $countstep - 1 ) ) )); #say  "\$y_value : " . dump( $y_value );
			$z_pace = ( $z_swing / ( $stepsvar - 1 ) ); #say  "\$z_pace : " . dump( $z_pace );
			$z_value = ($z_base + ( $z_end - ( $z_pace * ( $countstep - 1 ) ) )); #say  "\$z_value : " . dump( $z_value );
		}
		
		$x_value = sprintf( "%.3f", $x_value ); 
		$y_value = sprintf( "%.3f", $y_value );
		$z_value = sprintf( "%.3f", $z_value );
		
my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
i
e
$x_value $y_value $z_value
y
$yes_or_no_translate_obstructions
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";

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


sub translate_surfaces
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $translate_surface, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_; 
	#say TOFILE "got \$to : " . dump($to); #say TOFILE "got \$stepsvar : " . dump($stepsvar);
	#say TOFILE "got \$countop : " . dump($countop); #say TOFILE "got \$countstep : " . dump($countstep);
	#say TOFILE "got \$swap : " . dump($swap); #say TOFILE "got \$translate_surface : " . dump($translate_surface);
	#say TOFILE "got \$countvar : " . dump($countvar); #say TOFILE "got \$fileconfig : " . dump($fileconfig);
	
	my @applytype = @$swap; #say TOFILE "got \@applytype : " . dump(@applytype);
	my $zone_letter = $applytype[$countop][3]; #say TOFILE "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 TOFILE "got \$transform_type : " . dump($transform_type);
	my @surfs_to_transl = @{ $translate_surface->[$countop][1] }; #say TOFILE "got \@surfs_to_transl : " . dump(@surfs_to_transl);
	my @ends_movs = @{ $translate_surface->[$countop][2] };  #say TOFILE "got \@ends_movs : " . dump(@ends_movs);  # end points of the movements.
	my $yes_or_no_update_radiation = $$translate_surface[$countop][3]; #say TOFILE "got \$yes_or_no_update_radiation : " . dump($yes_or_no_update_radiation);
	my @transform_coordinates = @{ $translate_surface->[$countop][4] }; #say TOFILE "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, $base );

	foreach my $surface_letter (@surfs_to_transl)
	{ 	#say TOFILE "got \$surface_letter : " . dump($surface_letter);
		#say TOFILE "got \$stepsvar : " . dump($stepsvar);
		if ( $stepsvar > 1 )
		{
			#say TOFILE "got \$transform_type : " . dump($transform_type);
			if ($transform_type eq "a")
			{
				$end_mov = $ends_movs[$countsurface]; #say TOFILE "got \$end_mov : " . dump($end_mov);  say TOFILE "got \$countstep : " . dump($countstep);
				if ( ref ( $end_mov ) )
				{
					my $min = $end_mov->[0]; #say TOFILE "FROM REF got \$min : " . dump($min);
					my $max = $end_mov->[1]; #say TOFILE "FROM REF got \$max : " . dump($max);
					$swing_surf = ( $max - $min ); #say TOFILE "FROM REF got \$swing_surf : " . dump($swing_surf);
					$base = $min;
				}
				else
				{
					$swing_surf = ( $end_mov * 2 ); #say TOFILE "got \$swing_surf : " . dump($swing_surf);
					$base = - ( $swing_surf / 2 );
				}
				
				$pace = ( $swing_surf / ( $stepsvar - 1 ) ); #say TOFILE  "\$pace : " . dump( $pace );
				$movement = ( $base + ( $pace * ( $countstep - 1) ) ); #say TOFILE  "\$movement : " . dump( $movement );
				#say TOFILE "got \$end_mov : " . dump($end_mov); #say TOFILE "got \$countstep : " . dump($countstep); 
				
					
				my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
$transform_type
$movement
y
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";
				unless ($exeonfiles eq "n") 
				{ 
					print `$printthis`;
				}
				print TOFILE "
#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_begin, $y_begin, $z_begin, $x_end, $y_end, $z_end, $x_swing, $y_swing, $z_swing, $x_value, $y_value, $z_value );
				my ( @coord2, @coord1 );
					
				if ( ref( $coordinates_for_movement[0] ) )
				{
					@coord1 = @{ $coordinates_for_movement[0] }; #say  TOFILE "\@coord1 : " . dump( @coord1 );
					@coord2 = @{ $coordinates_for_movement[1] }; #say TOFILE  "\@coord2 : " . dump( @coord2 );
					( $x_begin, $y_begin, $z_begin ) = @coord1; #say TOFILE  "\$x_begin : " . dump( $x_begin ); say TOFILE  "\$y_begin : " . dump( $y_begin ); say TOFILE  "\$z_begin : " . dump( $z_begin );
					( $x_end, $y_end, $z_end ) = @coord2; #say TOFILE  "\$x_end : " . dump( $x_end );say TOFILE  "\$y_end : " . dump( $y_end );say TOFILE  "\$z_end : " . dump( $z_end );
					
					$x_swing = ( $x_end - $x_begin ); #say TOFILE  "\$x_swing : " . dump( $x_swing );
					$y_swing = ( $y_end - $y_begin ); #say TOFILE  "\$y_swing : " . dump( $y_swing );
					$z_swing = ( $z_end - $z_begin ); #say TOFILE  "\$z_swing : " . dump( $z_swing );
					
					$x_pace = ( $x_swing / ( $stepsvar - 1 ) ); #say TOFILE  "\$x_pace : " . dump( $x_pace );
					$y_pace = ( $y_swing / ( $stepsvar - 1 ) ); #say TOFILE  "\$y_pace : " . dump( $y_pace );
					$z_pace = ( $z_swing / ( $stepsvar - 1 ) ); #say TOFILE  "\$z_pace : " . dump( $z_pace );
					
					$x_value = ( $x_begin + ( $x_pace * ( $countstep - 1) ) ); #say TOFILE  "\$x_value : " . dump( $x_value );
					$y_value = ( $y_begin + ( $y_pace * ( $countstep - 1) ) ); #say TOFILE  "\$y_value : " . dump( $y_value );
					$z_value = ( $z_begin + ( $z_pace * ( $countstep - 1) ) ); #say TOFILE  "\$z_value : " . dump( $z_value );
					#say TOFILE "COUNTSTEP - 1 = ( $countstep - 1 )";
				}
				else
				{
					$x_end = $coordinates_for_movement[0]; #say  "\$x_end : " . dump( $x_end );
					$x_swing = ( 2 * $x_end ); #say  "\$x_swing : " . dump( $x_swing );
					$x_base = $base[0]; #say  "\$x_base : " . dump( $x_base );
					
					$y_end = $coordinates_for_movement[1]; #say  "\$y_end : " . dump( $y_end );
					$y_swing = ( 2 * $y_end ); #say  "\$y_swing : " . dump( $y_swing );
					$y_base = $base[1]; #say  "\$y_base : " . dump( $y_base );
					
					$z_end = $coordinates_for_movement[2]; #say  "\$z_end : " . dump( $z_end );
					$z_swing = ( 2 * $z_end ); #say  "\$z_swing : " . dump( $z_swing );
					$z_base = $base[2]; #say  "\$z_base : " . dump( $z_base );

					$x_pace = ( $x_swing / ( $stepsvar - 1 ) ); #say  "\$x_pace : " . dump( $x_pace );
					$x_value = ($x_base + ( $x_end - ( $x_pace * ( $countstep - 1 ) ) )); #say  "\$x_value : " . dump( $x_value );
					$y_pace = ( $y_swing / ( $stepsvar - 1 ) ); #say  "\$y_pace : " . dump( $y_pace );
					$y_value = ($y_base + ( $y_end - ( $y_pace * ( $countstep - 1 ) ) )); #say  "\$y_value : " . dump( $y_value );
					$z_pace = ( $z_swing / ( $stepsvar - 1 ) ); #say  "\$z_pace : " . dump( $z_pace );
					$z_value = ($z_base + ( $z_end - ( $z_pace * ( $countstep - 1 ) ) )); #say  "\$z_value : " . dump( $z_value );
				}
				
				$x_value = sprintf( "%.3f", $x_value ); 
				$y_value = sprintf( "%.3f", $y_value );
				$z_value = sprintf( "%.3f", $z_value );

				my $printthis = 
"prj $launchline<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
$transform_type
$x_value $y_value $z_value
y
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";

				unless ($exeonfiles eq "n") 
				{ 
					print `$printthis`;
				}

				print TOFILE "
#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, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	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 ( $base, $swingrotate, $pacerotate, $rotation_degrees, $vertex_number, $yes_or_no_apply );

	my $countrotate = 0;
	foreach my $surface_letter (@surfs_to_rotate)
	{
		$swingrotate = $swingrotations[$countrotate]; #say TOFILE  "\$swingrotate : " . dump( $swingrotate );

		if ( ref ( $swingrotate ) )
		{
			my $min = $swingrotate->[0]; #say TOFILE  "\$min : " . dump( $min );
			my $max = $swingrotate->[1]; #say TOFILE  "\$max : " . dump( $max );
			$swingrotate = ( $max - $min ); #say TOFILE  "\$swingrotate : " . dump( $swingrotate );
			$base = $min; #say TOFILE  "\$base : " . dump( $base );
		}
		else
		{
			$swingrotate = ( 2 * $swingrotate );
			$base = - ( $swingrotate / 2 ); #say TOFILE  "\$base : " . dump( $base );
		}

		$pacerotate = ( $swingrotate / ( $stepsvar - 1 ) ); #say TOFILE  "\$pacerotate : " . dump( $pacerotate );
		$rotation_degrees = $base + ( $pacerotate * ( $countstep - 1 ) ) ; #say TOFILE  "\$rotation_degrees : " . dump( $rotation_degrees );
		$vertex_number = $vertices_numbers[$countrotate];
		$yes_or_no_apply = $yes_or_no_apply_to_others[$countrotate];
		if (  ( $swingrotate != 0 ) and ( $stepsvar > 1 ) )
		{
			my $printthis =
"prj $launchline<<YYY

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

			print  TOFILE "
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
{
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $translate_vertices_ref, $countvar, $fileconfig , $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @translate_vertices = @$translate_vertices_ref; #say TOFILE  "\@translate_vertices : " . dump( @translate_vertices );
	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] }; #say TOFILE  "\@verts_to_transl : " . dump( @verts_to_transl );
	my @transform_coordinates = @{ $translate_vertices[$countop][1] }; #say TOFILE  "\@transform_coordinates : " . dump( @transform_coordinates );
	my @sourcefiles = @{ $translate_vertices[$countop][2] }; #say TOFILE  "\@sourcefiles : " . dump( @sourcefiles );
	
	my $sourcefile = $sourcefiles[ $countops ]; #say TOFILE  "\$sourcefile : " . dump( $sourcefile );
	my $sourceaddress = "$mypath/$file$sourcefile"; #say TOFILE  "\$sourceaddress : " . dump( $sourceaddress );
	
	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourceaddress 2: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;
		
	my $countlines = 0;
	my $countvert = 0;

	my @vertex_letters = (
	"a", 	"b", 	"c", 	"d", 	"e", 	"f", 	"g", 	"h", 	"i", 	"j", 	"k", 	"l", 	"m", 	"n", 	"o", 	"p", 
	"0\np", "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\nc",	"0\nd",	"0\ne",
	"0\n0\nb\ne", "0\n0\nb\nf", "0\n0\nb\ng", "0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", 
	"0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", "0\n0\nb\ns", "0\n0\nb\nt", 
	"0\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", 
	"0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", 
	"0\n0\nb\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\n0\nb\nj", "0\n0\nb\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\n0\nb\np", 
	"0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx"
	);
	

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

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

	my $countvertex = 0;		
	foreach my $base_coordinates_ref ( @transform_coordinates )
	{
		( $x_swing, $y_swing, $z_swing, $x_base, $y_base, $z_base );
		my $vertex_letter = $vertex_letters[ $countvertex ]; #say TOFILE  "\$vertex_letter : " . dump( $vertex_letter );
		my @basevs = @{ $v[ $countvertex ] }; #say TOFILE  "\@basevs : " . dump( @basevs );
		my ( $x_base, $y_base, $z_base, $vertexletter ) = ( $basevs[0], $basevs[1], $basevs[2], $basevs[3] ); #say TOFILE  "\$x_base, \$y_base, \$z_base, \$vertexletter : " . dump( $x_base, $y_base, $z_base, $vertexletter );
		
		my @base_coordinates = @{ $base_coordinates_ref }; #say TOFILE  "\@base_coordinates : " . dump( @base_coordinates );
		
		my $x_end = $base_coordinates[0]; #say TOFILE  "\$x_end : " . dump( $x_end );
		if ( ref ( $x_end ) )
		{
			my $min = $base_coordinates[0][0]; #say TOFILE  "\$min : " . dump( $min );
			my $max = $base_coordinates[1][0]; #say TOFILE  "\$max : " . dump( $max );
			$x_swing = ( $max - $min ); #say TOFILE  "\$x_swing : " . dump( $x_swing );
			$x_base = $x_base - $min; #say TOFILE  "\$x_base : " . dump( $x_base );
		}
		else
		{
			$x_swing = ( 2 * $x_end ); #say TOFILE  "\$x_swing : " . dump( $x_swing );
			$x_base = $x_base - ( $x_swing / 2 ); #say TOFILE  "\$x_base : " . dump( $x_base );
		}

		my $y_end = $base_coordinates[1];
		if ( ref ( $y_end ) )
		{
			my $min = $base_coordinates[0][1];
			my $max = $base_coordinates[1][1];
			$y_swing = ( $max - $min );
			$y_base = $y_base - $min;
		}
		else
		{
			$y_swing = ( 2 * $y_end );
			$y_base = $y_base - ( $y_swing / 2 );
		}
		
		my $z_end = $base_coordinates[2];
		if ( ref ( $z_end ) )
		{
			my $min = $base_coordinates[0][2];
			my $max = $base_coordinates[1][2];
			$z_swing = ( $max - $min );
			$z_base = $z_base - $min;
		}
		else
		{
			$z_swing = ( 2 * $z_end );
			$z_base = $z_base - ( $z_swing / 2 );
		}
		
		my $x_pace = ( $x_swing / ( $stepsvar - 1 ) );
		my $x_movement = ( $x_base + ( $x_pace * ( $countstep - 1 ) ) );
		my $y_pace = ( $y_swing / ( $stepsvar - 1 ) );
		my $y_movement = ( $y_base + ( $y_pace * ( $countstep - 1 ) ) );
		my $z_pace = ( $z_swing / ( $stepsvar - 1 ) );
		my $z_movement = ( $z_base + ( $z_pace * ( $countstep - 1 ) ) );
		
		$x_movement = sprintf( "%.3f", $x_movement ); 
		$y_movement = sprintf( "%.3f", $y_movement ); 
		$z_movement = sprintf( "%.3f", $z_movement ); 
		
		my $printthis =
"prj $launchline<<YYY

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

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


sub shift_vertices
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $shift_vertices, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	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];
	my ( $base );
	
	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];
					$base = $min;
					$shift_swing = ( $max - $min );
				}
				else 
				{
					$shift_swing = ( $shift_swing * 2 );
					$base = - ( $shift_swing / 2 );
				}
				
				$pace = ( $shift_swing / ( $stepsvar - 1 ) );
				$movement_or_vertex = ( $base + ( $pace * ( $countstep - 1 ) ) );
				$vertex1 = ( $pairs_of_vertices[ 0 + ( 2 * $countthis ) ] );
				$vertex2 = ( $pairs_of_vertices[ 1 + ( 2 * $countthis ) ] );
				
				my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
d
^
$movementtype
$vertex1
$vertex2
-
$movement_or_vertex
y
-
y
-
y
-
-
-
-
-
-
-
-
YYY
";
				unless ($exeonfiles eq "n") 
				{ 
					print `$printthis`;
				}
				print TOFILE "
#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 $launchline<<YYY

m
c
a
$zone_letter
d
^
$movementtype
$vertex1
$vertex2
-
$movement_or_vertex
-
y
n
n
n
-
y
-
y
-
-
-
-
-
-
-
-
YYY
";
				unless ($exeonfiles eq "n") 
				{ 
					print `$printthis`;
				}
				print TOFILE "
#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, $applytype_ref, $rotate, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref; #say "dump(\@applytype): " . dump(@applytype);
	my $zone_letter = $applytype[$countop][3]; #say "dump(\$zone_letter): " . dump($zone_letter);
	
	say "Rotating zones for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my ( $rotation_degrees, $pacerotate, $base ); 
	my $swingrotate = $$rotate[$countop][1]; #say "dump(\$swingrotate): " . dump($swingrotate);
	my $yes_or_no_rotate_obstructions = $$rotate[$countop][0]; #say "dump(\$yes_or_no_rotate_obstructions): " . dump($yes_or_no_rotate_obstructions);								
	my $yes_or_no_update_radiation = $$rotate[$countop][2]; #say "dump(\$yes_or_no_update_radiation): " . dump($yes_or_no_update_radiation);
	my $base_vertex = $$rotate[$countop][3]; #say "dump(\$base_vertex): " . dump($base_vertex);
	
	if ( ref ( $swingrotate ) )
	{
		my $begin = $swingrotate->[0]; #say "dump(\$min): " . dump($min);
		my $end = $swingrotate->[1]; #say "dump(\$max): " . dump($max);
		$swingrotate = ( $end - $begin ); #say "dump(\$swingrotate): " . dump($swingrotate);
		$base = $begin; 
	}
	else
	{
		$swingrotate = ( $swingrotate * 2 );
		$base = - ( $swingrotate / 2 );
	}
	
	$pacerotate = ( $swingrotate / ( $stepsvar - 1 ) ); #say "dump(\$pacerotate): " . dump($pacerotate);
	$rotation_degrees = ( $base + ( $pacerotate * ( $countstep - 1 ) ) ); #say "dump(\$rotation_degrees): " . dump($rotation_degrees);

	my $count_rotate = 0;
	
	if ( ( $swingrotate != 0 ) and ( $stepsvar > 1 ) )
	{
		
		my $printthis = 
"prj $launchline<<YYY


m
c
a
$zone_letter
i
b
$rotation_degrees
$base_vertex
-
$yes_or_no_rotate_obstructions
-
y
c
-
y
-
-
-
-
-
-
-
-
YYY
"; #say "dump(\$printthis): " . dump($printthis);

		unless ($exeonfiles eq "n") 
		{ 
			print `$printthis`;
		}
		print TOFILE 
		"
#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, $countmorphing, $launchline ) = @_;
	
	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 );
	}
	
	if ( ref ( $swingrotate ) )
	{
		my $min = $swingrotate->[0];
		my $max = $swingrotate->[1];
		$swingrotatexy = ( $max - $min );
	}
	
	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_);
		unless ($exeonfiles eq "n") { print `chmod 777 $infile`; }
		print TOFILE "chmod -R 777 $infile\n";
		unless ($exeonfiles eq "n") { print `chmod 777 $infile2`; }
		print TOFILE "chmod -R 777 $infile2\n";
		unless ($exeonfiles eq "n") { print `rm $infile`; }
		print TOFILE "rm $infile\n";
		unless ($exeonfiles eq "n") { print `chmod 777 $outfile2`; }
		print TOFILE "chmod 777 $outfile2\n";
		unless ($exeonfiles eq "n") { print `cp $outfile2 $infile`; }
		print TOFILE "cp $outfile2 $infile\n";
		unless ($exeonfiles eq "n") { print `cp $outfile2 $infile2`; }
		print TOFILE "cp $outfile2 $infile2\n";
	}
} # END SUB rotatez


sub reassign_construction
{
	my ( $to, $stepsvar, $countop, $countstep, $swap, $construction_reassignment, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	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 $launchline<<YYY

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

		print TOFILE "
#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, $applytype_ref, $thickness_change, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref; #say TOFILE "dump(\@applytype): " . dump(@applytype);
	my $zone_letter = $applytype[$countop][3]; #say TOFILE "dump(\$zone_letter): " . dump($zone_letter);
	
	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] }; #say TOFILE "dump(\@entries_to_change): " . dump(@entries_to_change);
	my @groups_of_strata_to_change = @{ $$thickness_change[$countop][1] }; #say TOFILE "dump(\@groups_of_strata_to_change): " . dump(@groups_of_strata_to_change);
	my @groups_of_couples_of_min_max_values = @{ $$thickness_change[$countop][2] }; #say TOFILE "dump(\@groups_of_couples_of_min_max_values): " . dump(@groups_of_couples_of_min_max_values);
	my $configfile = $$thickness_change[$countop][3]; # OPTIONAL
	
	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] }; #say TOFILE "dump(\@strata_to_change): " . dump(@strata_to_change);
			$countstrata = 0;
			foreach $stratum_to_change (@strata_to_change)
			{
				@min_max_values = @{ $groups_of_couples_of_min_max_values[$thiscount][$countstrata] }; #say TOFILE "dump(\@min_max_values): " . dump(@min_max_values);
				$min   = $min_max_values[0]; #say TOFILE "dump(\$min): " . dump($min);
				$max   = $min_max_values[1]; #say TOFILE "dump(\$max): " . dump($max);
				$swing = $max - $min; #say TOFILE "dump(\$swing): " . dump($swing);
				$pace  = ( $swing / ( $stepsvar - 1 ) ); #say TOFILE "dump(\$pace): " . dump($pace);
				$thickness = $min + ( $pace * ( $countstep - 1 ) ); #say TOFILE "dump(\$thickness): " . dump($thickness);

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


sub readobsfile
{  	# THIS READS A GEO FILE TO GET THE DATA OF THE REQUESTED OBSTRUCTIONS
	my ( $fullgeopath ) = @_; 
	
	#my @lines = `cat $fullgeopath`;
	open( GEOF, "<$fullgeopath" );
	my @lines = <GEOF>;
	close GEOF;
	#say "LINES: @lines";

	my $countelt = 0;
	my %obs_letter = ( 
				1 => "e", 2 => "f", 3 => "g", 4 => "h", 5 => "i", 6 => "j", 7 => "k", 8 => "l", 9 => "m", 10 => "n", 11 => "o", 
				12 => "0\no", 13 => "0\np", 14 => "0\nq", 15 => "0\nr", 16 => "0\ns", 17 => "0\nt", 18 => "0\nu", 19 => "0\nv", 20 => "0\nw", 21 => "0\nx", 22 => "0\ny", 
				23 => "0\n0\nb\ny", 24 => "0\n0\nb\nz", 25 => "0\n0\nb\na", 26 => "0\n0\nb\nb", 27 => "0\n0\nb\nc", 28 => "0\n0\nb\nd", 
				29 => "0\n0\nb\ne", 30 => "0\n0\nb\nf", 31 => "0\n0\nb\ng", 32 => "0\n0\nb\nh", 33 => "0\n0\nb\ni",
				34 => "0\n0\nb\n0\nb\ni", 35 => "0\n0\nb\n0\nb\nj", 36 => "0\n0\nb\n0\nb\nk", 37 => "0\n0\nb\n0\nb\nl", 38 => "0\n0\nb\n0\nb\nm", 39 => "0\n0\nb\n0\nb\nn", 
				40 => "0\n0\nb\n0\nb\no", 41 => "0\n0\nb\n0\nb\np", 42 => "0\n0\nb\n0\nb\nq", 43 => "0\n0\nb\n0\nb\nr", 44 => "0\n0\nb\n0\nb\ns",
				45 => "0\n0\nb\n0\nb\n0\nb\ns", 46 => "0\n0\nb\n0\nb\n0\nb\nt", 47 => "0\n0\nb\n0\nb\n0\nb\nv", 48 => "0\n0\nb\n0\nb\n0\nb\nw", 49 => "0\n0\nb\n0\nb\n0\nb\nx", 50 => "0\n0\nb\n0\nb\n0\nb\ny", 
				51 => "0\n0\nb\n0\nb\n0\nb\nz", 52 => "0\n0\nb\n0\nb\n0\nb\na", 53 => "0\n0\nb\n0\nb\n0\nb\nb", 54 => "0\n0\nb\n0\nb\n0\nb\nc", 55 => "0\n0\nb\n0\nb\n0\nb\nd",
			); # RE-CHECK
		
	my %obsts;

	foreach my $line (@lines)
	{
		if ( $line =~ m/^\*obs/ )
		{
			my @elts = split(/\s+|,/, $line);
			my $obsnum = $elts[13];
			my $obsletter = $obs_letter{$obsnum}; say  "\$obsletter : " . dump( $obsletter );
			$obsts{$obsletter}{obsnum} = $obsnum;
			$obsts{$obsletter}{origin} = [ @elts[ 1..3 ] ];
			$obsts{$obsletter}{dimensions} = [ @elts[ 4..6 ] ];
			$obsts{$obsletter}{z_rotation} = $elts[7];
			$obsts{$obsletter}{y_rotation} = $elts[8];
			$obsts{$obsletter}{name} = $elts[9];
			$obsts{$obsletter}{material} = $elts[10];
		}
	}
	return( %obsts );
}


sub obs_modify
{
	#say $tee "LANDED.";
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $obs_modify_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref; #say $tee "\@applytype : " . dump( @applytype );
	my $zone_letter = $applytype[$countop][3]; #say $tee "\$zone_letter : " . dump( $zone_letter );
	say $tee "Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";		
	my $case_cycle_ref = $obs_modify_ref->[$countop]; #say $tee "\$case_cycle_ref : " . dump( $case_cycle_ref );
	my @case_cycle = @$case_cycle_ref; #say $tee "\@case_cycle : " . dump( @case_cycle );
	my $geofile = shift( @case_cycle ); #say $tee "\$geofile : $geofile" ;
	my $configfile = $geofile; #say $tee "\$configfile : $configfile" ;
	my $fullgeopath = $mypath . "/" . $file. $geofile; #say $tee "\$fullgeopath : $fullgeopath" ;
	my @obsrefs = @case_cycle; #say $tee "\@obsrefs : " . dump( @obsrefs );

	my %obsts = readobsfile( $fullgeopath ); #say $tee "\%obsts : " . dump( %obsts );
	
	my $countobs = 0;
	foreach my $obs ( @obsrefs )
	{
		my $obsletter = $obs->[0]; #say $tee "\$obsletter : " . dump( $obsletter );
		my $modification_type = $obs->[1]; #say  "\$modification_type : " . dump( $modification_type );
		my $values_ref = $obs->[2]; #say  "\$values_ref : " . dump( $values_ref );
		
		my $xz_resolution = $obs->[3]; #say $tee "\$xz_resolution : " . dump( $xz_resolution ); # IT CAN BE ABSENT
		my ( $value, $basevalue, $swing, $low, $high );				  
		my ( $x_end, $y_end, $z_end, $zory_end, $x_base, $base, $y_base, $z_base, $end_value, $base_value, $swing, $x_swing, 
		$y_swing, $z_swing, $pace, $value, $x_pace, $x_value, $y_pace, $y_value, $z_pace, $z_value,
		$x_begin, $y_begin, $z_begin, $x_newbase, $y_newbase, $z_newbase );
		my ( @base, @values, @coord1, @coord2 );
		
		my $nofspaces = ( $stepsvar - 1 ); #say $tee "\$x_end : " . dump( $x_end ); # NUMBER OF SPACES BETWEEN STEPS

		if ( $modification_type eq "a" )
		{
			@base = @{ $obsts{$obsletter}{origin} }; #say $tee "\@base : " . dump( @base );
		}				  
		elsif ( $modification_type eq "b" )
		{
			@base = @{ $obsts{$obsletter}{dimensions} }; #say $tee "\@base : " . dump( @base );
		}
		elsif ( $modification_type eq "c" )
		{
			$base = $obsts{$obsletter}{z_rotation}; #say $tee "\$base : " . dump( $base );
		}
		elsif ( $modification_type eq "d" )
		{
			$base = $obsts{$obsletter}{y_rotation}; #say $tee "\$base : " . dump( $base );
		}
		elsif ( $modification_type eq "g" )
		{
			$base = $obsts{$obsletter}{name}; #say $tee "\$base : " . dump( $base );
		}
		elsif ( $modification_type eq "h" )
		{
			$base = $obsts{$obsletter}{material}; #say $tee "\$base : " . dump( $base );
		}
		
		if ( ( $modification_type eq "a" ) or ( $modification_type eq "b" ) )
		{      	
			my ( $x_base, $y_base, $z_base ) = @base;
					
			if ( ref( $values_ref->[0] ) )
			{
				#say $tee "x_base = $x_base, y_base = $y_base, z_base = $z_base"; 
				@coord1 = @{ $values_ref->[0] }; #say  $tee "\@coord1 : " . dump( @coord1 );
				@coord2 = @{ $values_ref->[1] }; #say $tee  "\@coord2 : " . dump( @coord2 );
				( $x_begin, $y_begin, $z_begin ) = @coord1; #say $tee  "\$x_begin : " . dump( $x_begin ); say $tee  "\$y_begin : " . dump( $y_begin ); say $tee  "\$z_begin : " . dump( $z_begin );
				( $x_end, $y_end, $z_end ) = @coord2; #say $tee  "\$x_end : " . dump( $x_end );say $tee  "\$y_end : " . dump( $y_end );say $tee  "\$z_end : " . dump( $z_end );
				
				$x_swing = ( $x_end - $x_begin ); #say $tee  "\$x_swing : " . dump( $x_swing );
				$y_swing = ( $y_end - $y_begin ); #say $tee  "\$y_swing : " . dump( $y_swing );
				$z_swing = ( $z_end - $z_begin ); #say $tee  "\$z_swing : " . dump( $z_swing );
				
				$x_newbase = ( $x_base + $x_begin ); #say $tee  "\$x_newbase : " . dump( $x_newbase );
				$y_newbase = ( $y_base + $y_begin ); #say $tee  "\$y_newbase : " . dump( $y_newbase ); 
				$z_newbase = ( $z_base + $z_begin ); #say $tee  "\$z_newbase : " . dump( $z_newbase );
				
				$x_pace = ( $x_swing / $nofspaces ); #say $tee  "\$x_pace : " . dump( $x_pace );
				$y_pace = ( $y_swing / $nofspaces ); #say $tee  "\$y_pace : " . dump( $y_pace );
				$z_pace = ( $z_swing / $nofspaces ); #say $tee  "\$z_pace : " . dump( $z_pace );
				
				$x_value = ( $x_newbase + ( $x_pace * ( $countstep - 1) ) ); #say $tee  "\$x_value : " . dump( $x_value );
				$y_value = ( $y_newbase + ( $y_pace * ( $countstep - 1) ) ); #say $tee  "\$y_value : " . dump( $y_value );
				$z_value = ( $z_newbase + ( $z_pace * ( $countstep - 1) ) ); #say $tee  "\$z_value : " . dump( $z_value );
				#say $tee "COUNTSTEP - 1 = ( $countstep - 1 )";
			}
			else
			{
				$values = $values_ref;
				$x_end = $values->[0]; #say $tee "\$x_end : " . dump( $x_end );
				$x_swing = ( 2 * $x_end ); #say $tee "\$x_swing : " . dump( $x_swing );
				$x_base = $base[0]; #say $tee "\$x_base : " . dump( $x_base );
				
				$y_end = $values->[1]; #say $tee "\$y_end : " . dump( $y_end );
				$y_swing = ( 2 * $y_end ); #say $tee "\$y_swing : " . dump( $y_swing );
				$y_base = $base[1]; #say $tee "\$y_base : " . dump( $y_base );
				
				$z_end = $values->[2]; #say $tee "\$z_end : " . dump( $z_end );
				$z_swing = ( 2 * $z_end ); #say $tee "\$z_swing : " . dump( $z_swing );
				$z_base = $base[2]; #say $tee "\$z_base : " . dump( $z_base );

				$x_pace = ( $x_swing / $nofspaces ); #say $tee "\$x_pace : " . dump( $x_pace );
				$x_value = ($x_base + ( $x_end - ( $x_pace * ( $countstep - 1 ) ) )); #say $tee "\$x_value : " . dump( $x_value );
				$y_pace = ( $y_swing / $nofspaces ); #say $tee "\$y_pace : " . dump( $y_pace );
				$y_value = ($y_base + ( $y_end - ( $y_pace * ( $countstep - 1 ) ) )); #say $tee "\$y_value : " . dump( $y_value );
				$z_pace = ( $z_swing / $nofspaces ); #say $tee "\$z_pace : " . dump( $z_pace );
				$z_value = ($z_base + ( $z_end - ( $z_pace * ( $countstep - 1 ) ) )); #say $tee "\$z_value : " . dump( $z_value );
			}
			
			$x_value = sprintf( "%.3f", $x_value );
			$y_value = sprintf( "%.3f", $y_value );
			$z_value = sprintf( "%.3f", $z_value );
			
			my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
h
a
$obsletter
$modification_type
a
$x_value $y_value $z_value
-
-
c
-
c
-
-
-
-
-
-
-
-
YYY
";

			say $tee "\$printthis : " . dump( $printthis );
			unless ($exeonfiles eq "n") 
			{ 
				print `$printthis`;
			} 
			print $tee "
#Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis"; say  "\$printthis : " . dump( $printthis );
		}


		if ( ($modification_type eq "c") or ($modification_type eq "d"))
		{      							  
			$zory_end = $value;
			
			if ( ref ( $zory_end ) )
			{
				my $min = $zory_end->[0];
				my $max = $zory_end->[1];
				$swingtranslate = ( $max - $min );
			}
			else 
			{ 
				$swingtranslate = ( 2 * $zory_end ); 
			}
		
			my $zory_base = $base;
			my $zory_pace = ( $swingtranslate / ( $stepsvar - 1 ) );
			my $zory_value = ($zory_base + ( $zory_end - ( $zory_pace * ( $countstep - 1 ) ) ));

			my $printthis = 
"prj $launchline<<YYY

m
c
a
$zone_letter
h
a
$obsletter
$modification_type
$zory_value
-
-
c
-
c
-
-
-
-
-
-
-
-
YYY
";
				unless ($exeonfiles eq "n") 
				{ 
					print `$printthis`;
				}
				print $tee "
#Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
		}

		if ($modification_type eq "g")
		{      	
			my @alternatives = @values;
			my $alternative = $alternatives[ $countobs ];				  
			my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
h
a
$obsletter
$modification_type
$alternative
-
-
-
-
-
-
-
-
-
-
-
-
-
-
YYY
";
			unless ($exeonfiles eq "n") 
			{ 
				print `$printthis`;
			}
			print $tee "
Modifying obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.
$printthis";
		}

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

			my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
h
a
$obsletter
$modification_type
$x_value
-
-
-
-
-
-
-
-
-
-
-
-
-
-
YYY
";
			unless ($exeonfiles eq "n")
			{ 
				print `$printthis`;
			}
			print $tee $printthis;
		}

		if ($modification_type eq "t")
		{      							  
			$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 ) ) );

			my $printthis =
"prj $launchline<<YYY

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

		if ( $xy_resolution ) # CUT THIS
		{
												
			my $printthis = #THIS IS WHAT HAPPEN INSIDE SUB KEEP_SOME_OBSTRUCTIONS
"prj $launchline<<YYY


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


sub recalculateish
{ 	
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $recalculateish, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	#say TOFILE "\$to: " . dump( $to );
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3]; #say $tee "\$zone_letter : " . dump( $zone_letter );
	#my @recalc = @{ $recalculateish->[ $countop ] }; say $tee "\@recalc " . dump( @recalc );
	
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{
		$launchline = " -file $to/cfg/$fileconfig -mode script";
	}
	else
	{
		$launchline = " -file $to\\cfg\\$fileconfig -mode script";
	}
	
	say $tee "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 $launchline<<YYY

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

	print TOFILE "
#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, $applytype_ref, $filedf, $swap2, $countvar, $fileconfig, $countmorphing, $launchline ) = @_;
	
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @daylightcalc = @$swap2;
	
	say $tee "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;
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{
		$pathdf = "$to/rad/$filedf";
	}
	else
	{
		$pathdf = "$to\\rad\\$filedf";
	}
	
	my $printthis;
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{
		
		if ( ifempty ( "$to/rad/" ) )
		{
			$printthis =
"
cd $to/cfg/
e2r $launchline<<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
";	
		}
		
		else
		{
			$printthis =
"
cd $to/cfg/
e2r $launchline<<YYY

a

a
d
$zone
-
$surface
$distance
$where
$edge
-
$density
y
$accuracy
a
-
-
-
-
-
YYY
\n\n
cd $mypath
";
		}
	}
	else
	{
		if ( ifempty ( "$to\\rad\\" ) )
		{
			$printthis =
"
cd $to\\cfg\\
e2r $launchline<<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
";	
		}
		
		else
		{
			$printthis =
"
cd $to\\cfg\\
e2r $launchline<<YYY

a

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

	print $tee "
#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, $applytype_ref, $change_config_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @change_config = @$change_config_ref;
	
	say $tee "Substituting a configuration file for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @change_conf = @{$change_config[ $countop ]};
	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 )
	{
		unless ($exeonfiles eq "n") 
		{ 
			unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
			{
				`cp -f $to/$new_configfile $to/$original_configfile\n`; 
			}
			else
			{
				`xcopy  /e /c /r /y $to\\$new_configfile $to\\$original_configfile\n`; 
			}
		}
		unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
		{
			print TOFILE "cp -f $to/$new_configfile $to/$original_configfile\n"; 
		}
		else
		{
			print TOFILE "xcopy  /e /c /r /y $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 "" ) or ( ( $sourceaddress eq $targetaddress ) ) )
	{
		print $tee "TARGETFILE IN FUNCTION: $targetaddress\n";
		if ( $sourceaddress ne $targetaddress )
		{
			unless ($exeonfiles eq "n") 
			{ 
				unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
				{
					`cp -f $sourceaddress $targetaddress\n`; 
				}
				else
				{
					`xcopy  /e /c /r /y $sourceaddress $targetaddress\n`; 
				}
			}
			unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
			{
				print TOFILE "cp -f $sourceaddress $targetaddress\n"; 
			}
			else
			{
				print TOFILE "xcopy  /e /c /r /y $sourceaddress $targetaddress\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, $stepsvar, $countop, $countstep, $applytype_ref, $change_climate_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	#say TOFILE "\$to : " . dump( $to ); 
	#say TOFILE "\$stepsvar : " . dump( $stepsvar ); 
	#say TOFILE "\$countop : " . dump( $countop );
	#say TOFILE "\$countstep : " . dump( $countstep ); 
	#say TOFILE "\$applytype_ref : " . dump( $applytype_ref ); 
	
	my @applytype = @{ $applytype_ref }; #say TOFILE "\@applytype : " . dump( @applytype );
	my $zone_letter = $applytype[$countop][3]; #say TOFILE "\$zone_letter : " . dump( $zone_letter );
	#say TOFILE "\$change_climate_ref : " . dump( $change_climate_ref ); 
	my @change_climates = @{ $change_climate_ref }; #say TOFILE "\@change_climates : " . dump( @change_climates );
	#say TOFILE "\$countvar : " . dump( $countvar ); 	#say TOFILE "\$countvar : " . dump( $countvar );
	
	say "Substituting climate database for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @climates = @{ $change_climates[ $countop ] }; #say TOFILE "\@climates : " . dump( @climates );
	my $newclimate = $climates[ $countstep - 1 ]; #say TOFILE "\$newclimate : " . dump( $newclimate );
	
	my $myfile;
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{
		$myfile = $to . "/cfg/" . $fileconfig;  #say TOFILE "\$myfile : " . dump( $myfile );
	}
	else
	{
		$myfile = $to . "\\cfg\\" . $fileconfig;  #say TOFILE "\$myfile : " . dump( $myfile );
	}
	
	open( FILECONFIG, $myfile ) or die( "$!" );
	
	my @lines = <FILECONFIG>;
	
	my $tempfileconfig = $myfile . ".temp";  #say TOFILE "\$tempfileconfig : " . dump( $tempfileconfig );
	open( TEMPFILECONFIG, ">$tempfileconfig" ) or die( "$!" );
		
	my ( $oldfile, $climatefolder );
	foreach my $line ( @lines )
	{
		if ( $line =~ /^\*clm/ )
		{
			my @row = split ( /\s+/ , $line ); #say TOFILE "\@row : " . dump( @row );
			$climatefile = $row[1]; #say TOFILE "\$climatefile : " . dump( $climatefile );
			$line =~ s/$climatefile/$newclimate/; #say TOFILE "\$line : " . dump( $line ); say TOFILE "\$climatefile : " . dump( $climatefile ); say TOFILE "\$newclimate : " . dump( $newclimate );
			print TEMPFILECONFIG $line;
		}
		else
		{
			print TEMPFILECONFIG $line;
		}
	}
	close FILECONFIG;
	close TEMPFILECONFIG;
	unless ( $exeonfiles eq "n" ) 
	{ 
		unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
		{
			`cp -R -f $tempfileconfig $myfile` ;
		}
		else
		{
			`xcopy  /e /c /r /y $tempfileconfig $myfile` ;
		}
	}
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{
		print TOFILE "cp -R -f $tempfileconfig $myfile" ;
	}
	else
	{
		print TOFILE "xcopy  /e /c /r /y $tempfileconfig $myfile" ;
	}

	print $tee "
#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, $applytype_ref, $recalculatenet_ref, $countvar, $fileconfig, $countmorphing, $launchline ) = @_;
	
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @recalculatenet = @$recalculatenet_ref->[ $countop ];
	
	say $tee "Adequating the ventilation network for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	
	my $filenet = $recalculatenet[0];
	
	my $infilenet;
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{
		$infilenet = "$mypath/$file/nets/$filenet";
	}
	else
	{
		$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", 
	"0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", "0\ny", "0\nz", "0\nz", "0\na", "0\nb", "0\nc", "0\nd", "0\ne", "0\nf",	"0\ng", "0\nh", 
	"0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", "0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", 
	"0\n0\nb\ns", "0\n0\nb\nt", "0\n0\nb\nu", "0\n0\nb\nv", "0\n0\nb\nw", "0\n0\nb\nx", "0\n0\nb\ny",
	"0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\nj", 
	"0\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\np", 
	"0\n0\nb\n0\nb\n0\nb\np", "0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\n0\nb\nb", 
	"0\n0\nb\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\n0\nb\ng"
	); # RE-CHECK
	
	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 $launchline<<YYY


m
e
c

n
c
$nodeletter

a
a
y
$zone

$height
a

-
-
y

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

				print TOFILE "
#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 $launchline<<YYY


m
e
c

n
c
$nodeletter

a
e
$zone
$interfaceletter
$calcpressurecoefficient
y

$height
-
-
y

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

					print TOFILE "
#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 $launchline<<YYY


m
e
c

n
d
$node_letters[$countthing]

k
-
$windareas[$countopening]
-
-
y

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

			print TOFILE "
#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 $launchline<<YYY


m
e
c

n
d
$node_letters[$countthing]

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

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

			print TOFILE $printthis;

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



sub pin_obstructions
{
	#use strict; use warnings;
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $pin_obstructions_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3]; #say TOFILE "\$zone_letter " . dump( $zone_letter );
	my @pin_obstructions = @{ $pin_obstructions_ref->[ $countop ] }; #say TOFILE "\@pin_obstructions " . dump( @pin_obstructions );
	my $sourcefile = shift( @pin_obstructions ); #say TOFILE "\$sourcefile " . dump( $sourcefile );
	my $sourcepath = $mypath . "/" . $file . $sourcefile; #say TOFILE "\$sourcepath " . dump( $sourcepath );
	my %keeplines ;
	my @newlines;
	open ( SOURCEFILE, $sourcepath ) or die( "$!" );
	my @sourcelines = <SOURCEFILE>;
	close SOURCEFILE;
	
	foreach my $obs ( @pin_obstructions )
	{
		foreach my $line ( @sourcelines )
		{
			if  ( ( $line =~ /^\*obs/ ) and ( $line =~ /$obs$/ ) ) 
			{
				$keeplines{$obs} = $line ; #say TOFILE "\$keeplines{\$obs} " . dump( $keeplines{$obs} );
			}
		}
	}
	my $targetpath = $to . $sourcefile; #say TOFILE "\$targetpath " . dump( $targetpath );
	my $oldfile = $targetpath . ".old"; #say TOFILE "\$oldfile " . dump( $oldfile );
	print TOFILE "mv -f $targetpath $oldfile\n";
	if ( $exeonfiles eq "y" )
	{
		print `mv -f $targetpath $oldfile`;
	}
	
	open( OLDFILE, $oldfile ) or die( "$!" );
	my @oldlines = <OLDFILE>;
	close OLDFILE;
	open ( NEWFILE, ">$targetpath" ) or die( "$!" );
	
	foreach my $line ( @oldlines )
	{
		if ( $line =~ /^\*obs/ )
		{
			foreach my $obs ( keys %keeplines )
			{
				if  ( $line =~ /$obs$/ )
				{
					$line = $keeplines{$obs}; 
					#print TOFILE "HERELINE " . $line;
				}
			}
		}
		if ( $exeonfiles eq "y" )
		{
			print NEWFILE $line;
		}
		#say TOFILE "PRINTING LINE";
		#print TOFILE $line;
	}
	close NEWFILE;	
	#no strict; no warnings;
} # END SUB pin_obstructions


sub apply_constraints
{
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $apply_constraints_ref, $countvar, $fileconfig, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @apply_constraints = @$apply_constraints_ref;
	my ( $value_reshape, $ybasewall, $ybasewindow );
	my @v;
	
	say $tee "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 ( $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";
			
			my $configaddress;
			unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
			{
				$configaddress = "$to/opts/$configfile";
			}
			else
			{
				$configaddress = "$to\\opts\\$configfile";
			}
			
			checkfile($sourceaddress, $targetaddress);
			
			if ( ref ( $swingvalue ) )
			{
				my $min = $swingvalue->[0];
				my $max = $swingvalue->[1];
				$swingvalue = ( $max - $min );
			}			

			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 = (
			"a", 	"b", 	"c", 	"d", 	"e", 	"f", 	"g", 	"h", 	"i", 	"j", 	"k", 	"l", 	"m", 	"n", 	"o", 	"p", 
			"0\np", "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\nc",	"0\nd",	"0\ne",
			"0\n0\nb\ne", "0\n0\nb\nf", "0\n0\nb\ng", "0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", 
			"0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", "0\n0\nb\ns", "0\n0\nb\nt", 
			"0\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", 
			"0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", 
			"0\n0\nb\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\n0\nb\nj", "0\n0\nb\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\n0\nb\np", 
			"0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx"
			);

			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 $launchline<<YYY

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

							print TOFILE "
#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, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	my @applytype = @$swap;
	my $zone_letter = $applytype[$countop][3];
	my @reshape_windows = @$swap2;
	
	say $tee "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 $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 $sourceaddress = "$to$sourcefile";
			my $targetaddress = "$to$targetfile";
			
			my $configaddress;
			unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
			{
				$configaddress = "$to/opts/$configfile";
			}
			else
			{
				$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 = (
			"a", 	"b", 	"c", 	"d", 	"e", 	"f", 	"g", 	"h", 	"i", 	"j", 	"k", 	"l", 	"m", 	"n", 	"o", 	"p", 
			"0\np", "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\nc",	"0\nd",	"0\ne",
			"0\n0\nb\ne", "0\n0\nb\nf", "0\n0\nb\ng", "0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", 
			"0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", "0\n0\nb\ns", "0\n0\nb\nt", 
			"0\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", 
			"0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", 
			"0\n0\nb\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\n0\nb\nj", "0\n0\nb\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\n0\nb\np", 
			"0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx"
			);			

			$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 $launchline<<YYY

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

							print TOFILE "
#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, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	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;
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{ 
		$configfile = $to."/opts/".$configfilename;
	}
	else
	{ 
		$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 $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 $launchline<<YYY

m
c
a
$zone_letter
e
>
$surface_letter
c
$vertex_number
$rotation_degrees
$yes_or_no_apply
-
-
y
c
-
-
-
-
-
-
-
-
YYY
";
			unless ($exeonfiles eq "n") 
			{ 
				print `$printthis`;
			}
			print  $tee "
#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 = (
	"a", 	"b", 	"c", 	"d", 	"e", 	"f", 	"g", 	"h", 	"i", 	"j", 	"k", 	"l", 	"m", 	"n", 	"o", 	"p", 
	"0\np", "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\nc",	"0\nd",	"0\ne",
	"0\n0\nb\ne", "0\n0\nb\nf", "0\n0\nb\ng", "0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", 
	"0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", "0\n0\nb\ns", "0\n0\nb\nt", 
	"0\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", 
	"0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", 
	"0\n0\nb\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\n0\nb\nj", "0\n0\nb\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\n0\nb\np", 
	"0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx"
	);
		
	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 $launchline<<YYY

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


sub export_toenergyplus
{
        my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $export_toenergyplus_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
        #say TOFILE "\$to " . dump( $to );
        #say TOFILE "\$countstep " . dump( $countstep );
        # say TOFILE "\$countop " . dump( $countop );
        my @applytype = @{ $applytype_ref->[ $countop ] }; #say TOFILE "\@applytype " . dump( @applytype );
        my @export_toenergypluses = @{ $export_toenergyplus_ref->[ $countop ] }; #say TOFILE "\@export_toenergypluses " . dump( @export_toenergypluses );
        shift( @export_toenergypluses );
        my $sim = shift( @export_toenergypluses ); #say TOFILE "\$sim " . dump( $sim );
        my $retrieve = shift( @export_toenergypluses ); #say TOFILE "\$retrieve " . dump( $retrieve );
        my $epw = shift( @export_toenergypluses ); #say TOFILE "\$epw " . dump( $epw );
       
        my $epwfile;
        unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
        { 
        	$epwfile = $mypath . "/" . $epw; #say TOFILE "\$epwfile " . dump( $epwfile );
        }
        else
        { 
        	$epwfile = $mypath . "\\" . $epw; #say TOFILE "\$epwfile " . dump( $epwfile );
        }
        
        say $tee "Exporting to EnergyPlus for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $file_eplus = "$to.idf";
	
	my $printthis =
"prj $launchline<<YYY

o
g
b
$file_eplus



-
-
YYY
";
	unless ($exeonfiles eq "n") 
	{ 
		`$printthis`;
	}
	print TOFILE 
	"#EXPORTING FILE $file_eplus TO ENERGYPLUS.\n
$printthis
";
	my $oldfile = $file_eplus; 
	$oldfile =~ s/\.idx//; 
	$oldfile = $oldfile . ".old.idx"; #say TOFILE "\$oldfile " . dump( $oldfile );
	
	unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
	{ 
		unless ( $exeonfiles eq "n" ) 
		{
			`mv -f $file_eplus $oldfile`;
		}
		print TOFILE "mv -f $file_eplus $oldfile\n";
	}
	else
	{
		unless ( $exeonfiles eq "n" ) 
		{
			`move /y $file_eplus $oldfile`;
		}
		print TOFILE "move /y $file_eplus $oldfile\n";
	}
	
	open ( OLDFILEEPLUS, $oldfile ) or die( "$!" );
	my @oldlines = <OLDFILEEPLUS>;
	close OLDFILEEPLUS;
	
	open ( NEWFILEEPLUS, ">$file_eplus" ) or die( "$!" );
	
	foreach my $line ( @oldlines )
	{
		foreach my $elt ( @export_toenergypluses )
		{
			my $old = $elt->[0];
			my $new = $elt->[1];
			$line =~ s/$old/$new/;
		}
		print NEWFILEEPLUS $line;
	}
	close NEWFILEEPLUS;
	
	if ( $sim )
	{
		unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
		{ 
			unless ( $exeonfiles eq "n" )
			{
				`runenergyplus $file_eplus $epwfile`;
			}
			print TOFILE "runenergyplus $file_eplus $epwfile\n"; # EPW FILE, FOR INSTANCE: /usr/local/EnergyPlus-7-2-0/WeatherData/USA_CA_San.Francisco.Intl.AP.724940_TMY3.epw
		}
		else
		{
			unless ( $exeonfiles eq "n" )
			{
				`runeplus $file_eplus $epwfile`;
			}
			print TOFILE "runeplus $file_eplus $epwfile\n"; # EPW FILE, FOR INSTANCE: /usr/local/EnergyPlus-7-2-0/WeatherData/USA_CA_San.Francisco.Intl.AP.724940_TMY3.epw
		}
	}
	
	if ( $retrieve )
	{
		#retrieveepw( $TO_DO );
	}
}


sub use_modish
{
	#use strict;
	#use warnings;
	#say TOFILE "\BEFORE: \$countvar " . dump( $countvar );
        my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $use_modish_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
        say TOFILE "\$launchline " . dump( $launchline );
        #say TOFILE "\AFTER \$countvar " . dump( $countvar );
        my @applytype = @$applytype_ref; #say TOFILE "\@applytype " . dump( @applytype );
        my @use_modish = @{ $use_modish_ref->[ $countop ] }; say TOFILE "\@use_modish " . dump( @use_modish );
        my $pathhere = "$to/cfg/$fileconfig"; say TOFILE "\$pathhere " . dump( $pathhere );
        say $tee "Executing modish.pl for calculating the effect of solar reflections on obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
        say TOFILE "IN MODISH \$launchline : $launchline" ;
        my %numletter = ( 1 => "a", 2 => "b", 3 => "c", 4 => "d", 5 => "e", 6 => "f", 7 => "g", 8 => "h", 9 => "i", 10 => "j", 11 => "k", 12 => "l", 13 => "m", 14 => "o" ); # ZZZ THESE LETTERS HAVE TO BE CHECKED WITH REGARDS TO THE CHANGE OF PAGES!

        if ( @use_modish )
        {
        	foreach $cycle_ref ( @use_modish )
        	{
        		my @cycle = @$cycle_ref; say TOFILE "\@cycle " . dump( @cycle );
			my $zonenumber = $cycle[0]; say TOFILE "\$zonenumber " . dump( $zonenumber );
			my $shdname = $to . $cycle[1]; #say TOFILE "\$shdname " . dump( $shdname );
			my $shdaname = $shdname . "a"; #say TOFILE "\$shdaname " . dump( $shdaname );
			my @surfaces = @cycle[ 2..$#cycle ]; #say TOFILE "\@surfaces " . dump( @surfaces );
			my $oldshdname = $shdname . ".old"; #say TOFILE "\$oldshdname " . dump( $oldshdname );
			my $oldshdaname = $shdaname . ".old"; #say TOFILE "\$oldshdaname " . dump( $oldshdaname );
			my $tempname = $shdname;
			$tempname =~ s/.shd//; #say TOFILE "\$tempname " . dump( $tempname );
			my $modshdaname = $tempname . ".mod.shda"; #say TOFILE "\$modshdaname " . dump( $modshdaname );
			$" = " ";
			
			unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
			{
				print TOFILE "perl $mypath/modish.pl $to/cfg/$fileconfig $zonenumber @surfaces\n";
				`perl $mypath/modish.pl $to/cfg/$fileconfig $zonenumber @surfaces`;
				
				`cp -f $shdname $oldshdname`;
				print TOFILE "cp -f $shdname $oldshdname\n";
				`cp -f $shdaname $oldshdname`;
				print TOFILE "cp -f $shdname $oldshdname\n";
				`cp -f $modshdaname $shdaname`;
				print TOFILE "cp -f $modshdaname $shdaname\n";
			}
			else
			{
				print TOFILE "perl $mypath/modish.pl $to\\cfg\\$fileconfig $zonenumber @surfaces\n";
				`perl $mypath\\modish.pl $to\\cfg\\$fileconfig $zonenumber @surfaces`;
				
				`xcopy  /e /c /r /y $shdname $oldshdname`;
				print TOFILE "xcopy  /e /c /r /y $shdname $oldshdname\n";
				`xcopy  /e /c /r /y $shdaname $oldshdname`;
				print TOFILE "xcopy  /e /c /r /y $shdname $oldshdname\n";
				`xcopy  /e /c /r /y $modshdaname $shdaname`;
				print TOFILE "xcopy  /e /c /r /y $modshdaname $shdaname\n";
			}
			unless ($exeonfiles eq "n") 
			{ 
				print `$printthis`;
			}
			my $printthis =
"prj $launchline<<YYY

m
c
f
$numletter{$zonenumber}

y
m
b

-
y
-
-
-
-
YYY
";
			print TOFILE 
			"RUNNING modish.pl.\n
$printthis
";
		}
	}
	no strict;
	no warnings;
}


sub genchange
{	# TO DO: POSSIBILITY TO SPECIFY TEXT STRINGS IN PLACE OF ELEMENTS
	#say TOFILE "NOW IN GENCHANGE.";				
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $genchange, $countvar, $fileconfig, $mypath, $file, 
	$countmorphing, $propop, $names_ref, $nums_ref, $newcontents_ref, 
	$filecontents_ref, $newfilecontents_ref, $launchline ) = @_;
	#say TOFILE "HERE'S \$to : $to "; #say TOFILE "PROPOP: $propop";
	#say TOFILE "HERE'S \$countvar $countvar";
	#say TOFILE "\$countmorphing " . dump( $countmorphing );												
	my @applytype = @$applytype_ref; #say TOFILE "\@applytype " . dump( @applytype );
	#my %names = %$names_ref; #
	#my %nums = %$nums_ref;
	#my %newcontents = %$newcontents_ref;
	#say TOFILE "\$propop " . dump( $propop );
	
	say $tee "Executing change for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	my $this_cycledata = $genchange->[$countop]; #say TOFILE "\$this_cycledata " . dump( $this_cycledata );
	my @filequestions = @{ $this_cycledata->[1] }; #say TOFILE "\@filequestions " . dump( @filequestions );
	my ( @plaincontents, @filecontents, @newfilecontents );
	my ( %names, %nums, %newcontents );
	
	
	
	
	sub read_gen
	{	
		my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $genchange, $countvar, $fileconfig, $mypath, $file, 
			$countmorphing, $propop, $names_ref, $nums_ref, $newcontents_ref, 
			$filecontents_ref, $newfilecontents_ref, $launchline, $fullfilepath, $new_fullfilepath, $filequestions_ref ) = @_;
		my @filequestions = @$filequestions_ref; #say TOFILE "\@filequestions " . dump( @filequestions );
		my $countunique = 1;
		my $countfile = 0;		
		foreach my $filequests ( @filequestions )
		{	#say TOFILE "INFILE QUEST2 \$countfile $countfile, \$countstep " . dump( $countstep );
			my @truequests = @$filequests; #say TOFILE "\@truequests " . dump( @truequests );	
			my $constrainfiles_ref = shift( @truequest );
			my @constrainfiles = @{ $constrainfiles_ref }; #say TOFILE "\@constrainfiles " . dump( @constrainfiles );
			my $thisfile = shift( @truequests );  #say TOFILE "\$thisfile " . dump( $thisfile ); say TOFILE "\@truequests " . dump( @truequests );
			my $fullfilepath = $to . $thisfile ; #say TOFILE "\$fullfilepath " . dump( $fullfilepath );
			my $new_fullfilepath = $fullfilepath . ".new" ; #say TOFILE "\$new_fullfilepath " . dump( $new_fullfilepath );
			
			open( FULLFILEPATH, "$fullfilepath" ) or die ( "$!" );
			my @filerows = <FULLFILEPATH>;
			my @passrows = @filerows;
			close FULLFILEPATH;
			@{ $plaincontents[ $countfile ] } = @filerows;

			#say TOFILE "HERE'S THE FILE: \@filerows: @filerows";
			#say TOFILE "SCALAR \@filerows : ". scalar( @filerows );
			
			
		
			#say TOFILE "HERE'S THEN \$to : $to "; #say TOFILE "PROPOP: $propop";
			my $countro = 0;
			foreach my $row ( @filerows )
			{	#say TOFILE "\IN READGEN "; say TOFILE "3 \$countstep " . dump( $countstep );
				my $newrow = "";
				$row =~ s/^\s+//; # CLEAR WHITE SPACES AT THE BEGINNING OF THE LINE
				$row =~ s/\s+//g; # MAKE SEQUENCES OF WHITE SPACES ONE SPACE
				my @rowelts = split( /\s+|,|;/, $row );
				@{ $filecontents[ $countfile ][ $countro ] } = @rowelts ;
				#$plaincontents[ $countfile ][ $countro ] = $row;
				
				#my $count = 0;
				#foreach my $el ( @rowelts )
				#{
				#	$filecont{$countfile}{$countro}{$count} = $el ;
				#	$count++;
				#}
				$countro++;
			} #say TOFILE "PRODUCED \@filecontents: " . dump( @filecontents );
			#@newfilecontents = @filecontents;
			#say TOFILE "INFILE QUEST3 \$countfile $countfile, \$countstep " . dump( $countstep );
			$countrow = 0;
			foreach my $row ( @filerows )
			{	#say TOFILE "\IN READGEN "; say TOFILE "4 \$countstep " . dump( $countstep );
				#say TOFILE "FOREACH \$row : ". scalar( $row );
				my $countquest = 0;
				my $countcoord = 0;
				foreach my $quest ( @truequests )
				{
					#say TOFILE "THESE \@truequests are " . dump( @truequests ) . " and are made for \$countvar $countvar";
					if ( defined ( @$quest ) )
					{	#say TOFILE "5 \$countstep " . dump( $countstep );
						my @row_numbers_plus1 = @{ $quest->[0] }; #say TOFILE "HARD STUFF \@row_numbers_plus1 " . dump( @row_numbers_plus1 );
						my @row_numbers = decreasearray( @row_numbers_plus1 ); #say TOFILE "\@row_numbers " . dump( @row_numbers ); 
						my $countrownum = 0;
						foreach my $row_number ( @row_numbers )
						{	#say TOFILE "YES HERE \$row_number $row_number";
							my @elts_pos_plus1 = @{ $quest->[1] }; #say TOFILE "\@elts_pos_plus1 @elts_pos_plus1" . dump( @elts_pos_plus1 );
							my @elts_pos = decreasearray( @elts_pos_plus1 ); #say TOFILE "\@elts_pos " . dump( @elts_pos );
										
							my $range = $quest->[2]; #say TOFILE "\$range " . dump( $range );
							my @nicknames = @{ $quest->[3] }; #say TOFILE "\@nicknames " . dump( @nicknames );
							#if ( scalar( @nicknames ) == 0 )
							#{
							#	@nicknames = @row_numbers_plus1;
							#}
							my $operation_type = $quest->[4]; #say TOFILE "\$operation_type " . dump( $operation_type );
							my $separator =  $quest->[5]; #say TOFILE "\$separator " . dump( $separator );
							my $centrexyz = $quest->[6]; #say TOFILE "\$centrexyz " . dump( $centrexyz );
							my $centrex = $centrexyz->[0]; #say TOFILE "\$centrex " . dump( $centrex );
							my $centrey = $centrexyz->[1]; #say TOFILE "\$centrey " . dump( $centrey );
							my $centrez = $centrexyz->[2]; #say TOFILE "\$centrez " . dump( $centrez );
							

							my @rowelts = @{ $filecontents[ $countfile ][ $countrow ] }; #say TOFILE "ARRIVED \@rowelts " . dump( @rowelts ); 
							
							
							my $countpos = 0;						
							foreach $elt_position ( @elts_pos )
							{ 	#say TOFILE "6 \$countstep " . dump( $countstep );
								my $countelt = 0;
								#say TOFILE "YES HERE \$elt_position $elt_position";
								foreach my $rowelt ( @rowelts )
								{	#say TOFILE "7 \$countstep " . dump( $countstep );
									my ( $truerange, $low, $high, $pace, $value, $base, $newvalue, $newangle );
									if ( ( $rowelt ne "" ) and  ( $rowelt ne " " ) )
									{ 	#say TOFILE "\$row_number " . dump( $row_number ); say TOFILE "\$countrow + 1 " . dump( $countrow + 1 ); 
										#say TOFILE "\$elt_position " . dump( $elt_position ); say TOFILE "\$countelt + 1 " . dump( $countelt + 1 ); 
										my @coords;
										if ( ( $row_number == $countrow ) and ( $elt_position == $countelt ) )
										{	#say TOFILE "FOUND."; say TOFILE "FOR \@rowelts " . dump( @rowelts ); say TOFILE "FOR \$row_number " . dump( $row_number );  say TOFILE "\$countstep " . dump( $countstep );
											#say TOFILE "APPROACHED \@elts_pos " . dump( @elts_pos ); say TOFILE "\$range " . dump( $range );
											#say TOFILE "FOR \$countrow + 1 : " . dump( $countrow + 1 ); say TOFILE "FOR \$elt_position " . dump( $elt_position ); say TOFILE "FOR \$countelt + 1 " . dump( $countelt + 1 );
											#say TOFILE "HAVE: OLDVALUE \$rowelt : " . dump( $rowelt ); say TOFILE "FOR \$countpos " . dump( $countpos );
											#say TOFILE "OTHERWAY \$elt_position: \$elts_pos[ \$countpos ] : " . dump( $elts_pos[ $countpos ] );
											my $next_elt_position = $elts_pos[ $countpos + 1 ]; #say TOFILE "\$next_elt_position " . dump( $next_elt_position );
											my $prev_elt_position = $elts_pos[ $countpos - 1 ]; #say TOFILE "\$prev_elt_position " . dump( $prev_elt_position );
											#say TOFILE "\$rowelts[ \$next_elt_position ] : $rowelts[ $next_elt_position ] ";
											#say TOFILE "\$rowelts[ \$prev_elt_position ] : $rowelts[ $prev_elt_position ] ";
			
											if ( defined( $range ) and ( $range ne "" ) )
											{
												if ( not ( defined( $operation_type ) ) )
												{
													$operation_type = "linear"; #LINEAR TRANSFORMATION.
												}
												
												if ( $operation_type eq "linear" )
												{
													if ( not ( ref( $range ) ) )
													{
														$truerange = ( 2 * $range ); #say TOFILE "IN: LINEAR TRANSFORMATION SIMPLE \$truerange " . dump( $truerange );
														$base = ( $rowelt - $range ); #say TOFILE "SIMPLE \$base " . dump( $base );
													}
													else
													{
														( $low, $high ) = ( $range->[0], $range->[1] );
														$truerange = ( $high - $low ); #say TOFILE "DERIVED \$truerange " . dump( $truerange );
														$base = ( $rowelt + $low ); #say TOFILE "DERIVED \$base " . dump( $base );
													}
													
													$pace = ( $truerange / ( $stepsvar - 1 ) ); #say TOFILE "THIS IS + \$pace: " . dump( $pace );  say TOFILE "\$rowelt " . dump( $rowelt ); say TOFILE "\$stepsvar " . dump( $stepsvar );  say TOFILE "\$countstep " . dump( $countstep );
													$newvalue = ( $base + ( $pace * ( $countstep - 1 ) ) ); #say TOFILE "\$newvalue " . dump( $newvalue ); 
												} # INSERT HERE WHAT HAPPENS IF THE TRANSFORMATION IS NOT LINEAR.
												
												if ( $operation_type eq "rotation2d" )
												{	
													$countcoord++;					
													if ( not ( ref( $range ) ) )
													{
														$truerange = ( 2 * $range ); #say TOFILE "INROTATION SIMPLE \$truerange " . dump( $truerange );
														$base = - $range; #say TOFILE "SIMPLE \$base " . dump( $base );
													}
													else
													{
														( $low, $high ) = ( $range->[0], $range->[1] );
														$truerange = ( $high + $low ); #say TOFILE "DERIVED \$truerange " . dump( $truerange );
														$base = - $low; #say TOFILE "DERIVED \$base " . dump( $base );
													}
													
													$pace = ( $truerange / ( $stepsvar - 1 ) ); #say TOFILE "DERIVED \$pace " . dump( $pace );
													$newangle = ( $base + ( $pace * ( $countstep - 1 ) ) ); #say TOFILE "DERIVED \$newangle " . dump( $newangle );
													
													my $next_elt_position = $elts_pos[ $countelt + 1  ]; #say TOFILE "\$next_elt_position " . dump( $next_elt_position );
													my $prev_elt_position = $elts_pos[ $countelt - 1  ] ; #say TOFILE "\$prev_elt_position " . dump( $prev_elt_position );
							
													if ( $countcoord == 1 )
													{	
														#say TOFILE "AT \$countrow : $countrow, \$elt_position : $elt_position ";
														#say TOFILE "FIRST COORD (CURRENT) : \$rowelt " . dump( $rowelt );
														#say TOFILE "SECOND COORD (NEXT): \$filecontents[ \$countfile ][ \$row_number ][ \$next_elt_position ] : " . dump( $filecontents[ $countfile ][ $row_number ][ $next_elt_position ]  );
														#my @obtained = rotate2d( $rowelt, $filecontents[ $countfile ][ $row_number ][ $next_elt_position ]  , $newangle, $centrex, $centrey );  say TOFILE "DERIVED \@obtained " . dump( @obtained );
														my @obtained = rotate2d( $rowelt, $rowelts[ $next_elt_position ] , $newangle, $centrex, $centrey );  say TOFILE "DERIVED \@obtained " . dump( @obtained );
														$newvalue = $obtained[0]; 
														if ( ( $newvalue < 0.00001 ) and ( $newvalue > - 0.00001 ) ){ $newvalue = 0; } ; #say TOFILE "DERIVED1 \$newvalue " . dump( $newvalue );
														
													}
													elsif ( $countcoord == 2 ) 
													{
														#say TOFILE "AT \$countrow : $countrow, \$elt_position : $elt_position ";
														#say TOFILE "FIRST COORD (PREVIOUS): \$filecontents[ \$countfile ][ \$row_number ][ \$prev_elt_position ] " . dump( $filecontents[ $countfile ][ $row_number ][ $prev_elt_position ] );
														#say TOFILE "SECOND COORD (NEXT): CURRENT \$rowelt " . dump( $rowelt );
														#my @obtained = rotate2d ( $filecontents[ $countfile ][ $row_number ][ $prev_elt_position ] , $rowelt, $newangle, $centrex, $centrey ); say TOFILE "DERIVED \@obtained " . dump( @obtained );
														my @obtained = rotate2d ( $rowelts[ $prev_elt_position ], $rowelt, $newangle, $centrex, $centrey ); say TOFILE "DERIVED \@obtained " . dump( @obtained );
														$newvalue = $obtained[1]; 
														#if ( ( $newvalue < 0.00001 ) and ( $newvalue > - 0.00001 ) ) { $newvalue = 0; } ; #say TOFILE "DERIVED2 \$newvalue " . dump( $newvalue );
														$countcoord = 0;
													}
												}
												
												if ( $operation_type eq "rotation2d_multiline" )
												{	
													$countcoord++;					
													if ( not ( ref( $range ) ) )
													{
														$truerange = ( 2 * $range ); #say TOFILE "INROTATION SIMPLE \$truerange " . dump( $truerange );
														$base = - $range; #say TOFILE "SIMPLE \$base " . dump( $base );
													}
													else
													{
														( $low, $high ) = ( $range->[0], $range->[1] );
														$truerange = ( $high + $low ); #say TOFILE "DERIVED \$truerange " . dump( $truerange );
														$base = - $low; #say TOFILE "DERIVED \$base " . dump( $base );
													}
													
													$pace = ( $truerange / ( $stepsvar - 1 ) ); #say TOFILE "DERIVED \$pace " . dump( $pace );
													$newangle = ( $base + ( $pace * ( $countstep - 1 ) ) ); #say TOFILE "DERIVED \$newangle " . dump( $newangle );
													
													if ( $countcoord == 1 )
													{	
														#say TOFILE "AT \$countrow : $countrow, \$elt_position : $elt_position ";
														#say TOFILE "FIRST COORD (CURRENT) : \$rowelt " . dump( $rowelt );
														#say TOFILE "SECOND COORD (NEXT): \$filecontents[ \$countfile ][ \$next_row_number ][ \$elt_position ] : " . dump( $filecontents[ $countfile ][ $next_row_number ][ $elt_position ]  );
														#say TOFILE "SECOND COORD CHECK (NEXT): \$filecontents[ \$countfile ][ \$row_number ][ \$elt_position ] : " . dump( $filecontents[ $countfile ][ $row_number ][ $elt_position ]  );
														#my @obtained = rotate2d( $rowelt, $filecontents[ $countfile ][ $next_row_number ][ $elt_position ]  , $newangle, $centrex, $centrey );  #say TOFILE "DERIVED \@obtained " . dump( @obtained );
														$newvalue = $obtained[0]; 
														if ( ( $newvalue < 0.00001 ) and ( $newvalue > - 0.00001 ) ){ $newvalue = 0; } ; #say TOFILE "DERIVED1 \$newvalue " . dump( $newvalue );
													}
													elsif ( $countcoord == 2 ) 
													{
														#say TOFILE "FIRST COORD (PREVIOUS): \$filecontents[ \$countfile ][ \$prev_row_number ][ \$elt_position ] " . dump( $filecontents[ $countfile ][ $prev_row_number ][ $elt_position ] );
														#say TOFILE "FIRST COORD CHECK (PREVIOUS): \$filecontents[ \$countfile ][ \$row_number ][ \$elt_position ] " . dump( $filecontents[ $countfile ][ $row_number ][ $elt_position ] );												say TOFILE "FIRST COORD (PREVIOUS): \$filecontents[ \$countfile ][ \$row_number ][ \$prev_elt_position ] " . dump( $filecontents[ $countfile ][ $row_number ][ $prev_elt_position ] );
														#say TOFILE "SECOND COORD (NEXT): CURRENT \$rowelt " . dump( $rowelt );
														#my @obtained = rotate2d ( $filecontents[ $countfile ][ $prev_row_number ][ $elt_position ] , $rowelt, $newangle, $centrex, $centrey ); #say TOFILE "DERIVED \@obtained " . dump( @obtained );
														my @obtained = rotate2d ( $filecontents[ $countfile ][ $prev_row_number ][ $elt_position ], $rowelt, $newangle, $centrex, $centrey ); #say TOFILE "DERIVED \@obtained " . dump( @obtained );
														$newvalue = $obtained[1]; 
														#if ( ( $newvalue < 0.00001 ) and ( $newvalue > - 0.00001 ) ) { $newvalue = 0; } ; #say TOFILE "DERIVED2 \$newvalue " . dump( $newvalue );
														$countcoord = 0;
													}
												}	
																					
											}
											elsif ( ( $range ne "" ) and ( $operation_type eq "" ) )
											{
												$newvalue = $rowelt; #say TOFILE "WRITE \$newvalue " . dump( $newvalue );
											}
											#say TOFILE "WRITE \$newvalue " . dump( $newvalue );
											
											my $nickname;
											if ( scalar( @nicknames ) == 0 )
											{
												$nickname = $countvar . "-" . ( $countrow + 1) . "-" . ( $countelt + 1 );
											}
											#say TOFILE "\$nickname : $nickname ";
											my $thisline = $passrows[$countrows];
											$names{$nickname} =
											{
												oldvalue => $rowelt,
												countfile => $countfile,
												countrow => $countrow,
												countelt => $countelt,
												newvalue => $newvalue,
												fullfilepath => $fullfilepath,
												countquest => ( $countquest + 1 ),
												nickname => $nickname,
												row => $thisline,
												separator => $separator
											};
											
											$nums{$countunique} =
											{
												oldvalue => $rowelt,
												countfile => $countfile,
												countrow => $countrow,
												countelt => $countelt,
												newvalue => $newvalue,
												fullfilepath => $fullfilepath,
												countquest => ( $countquest + 1 ),
												nickname => $nickname,
												row => $thisline,
												separator => $separator
											};
											$countunique++;	
										}
									}
									$countelt++;	
								}
								$countpos++;
							}
							$countrownum++;
						}
					}
					$countquest++;
				}
				$countrow++;
			}
			$countfile++;
		}
		return (  \%names, \%nums, \%newcontents, \@newfilecontents, \@plaincontents, \@filecontents );
	}
	
	if ( ( $propop eq "read_gen" ) or ( $propop eq "vary" ) )
	{
		( $names_ref, $nums_ref, $newcontents_ref, $newfilecontents_ref, $plaincontents_ref, $filecontents_ref ) = 
		read_gen( $to, $stepsvar, $countop, $countstep, $applytype_ref, $genchange, $countvar, $fileconfig, $mypath, $file, 
				$countmorphing, $propop,  $names_ref, $nums_ref, $newcontents_ref, 
				$filecontents_ref, $newfilecontents_ref, $launchline, , $fullfilepath, $new_fullfilepath, \@filequestions );
		%names = %$names_ref; #say TOFILE "OUT_PUT READ_GEN \%names " . dump( %names );
		%nums = %$nums_ref; #say TOFILE "OUT_PUT READ_GEN \%nums " . dump( %nums );
		%newcontents = %$newcontents_ref; #say TOFILE "OUT_PUT READ_GEN \%newcontents " . dump( %newcontents );
		@newfilecontents = @$newfilecontents_ref; #say TOFILE "OUT_PUT READ_GEN \@newfilecontents " . dump( @newfilecontents );
		@plaincontents = @$plaincontents_ref; #say TOFILE "OUT_PUT READ_GEN \@plaincontents " . dump( @plaincontents );
		@filecontents = @$filecontents_ref; #say TOFILE "OUT_PUT READ_GEN \@filecontents " . dump( @filecontents );
	}
	sub read_gen_constraints
	{	#say TOFILE "NOW evalcat";
		my ( $constrainfiles_ref, $names_ref, $newcontents_ref ) = @_;
		my @constrainfiles = @$constrainfiles_ref;
		my %names = %$names_ref;
		my %newcontents = %$newcontents_ref;
		foreach my $constrainfile ( @constrainfiles )
		{
			if ( ( -e $constrainfile ) and ( defined( $constrainfile ) ) )
			{	
				eval `cat $constrainfile`; #say TOFILE "IT HAPPENDED 0!"; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED. THE SUBJECT IS %NAMES
			}
		}

		#say TOFILE "NOW foreach nickname";
		foreach my $nickname ( sort {$a <=> $b} ( keys %names ) )
		{
			if ( defined( $nickname ) )
			{
				$newcontents{$names{$nickname}{countfile}}{$names{$nickname}{countrow}}{$names{$nickname}{countquest}}{$names{$nickname}{countelt}} = $names{$nickname}{newvalue} ; say TOFILE "IT HAPPENDED 1!";
			}
		}
		return ( \%names, \%newcontents );
	}
	
	if ( ( $propop eq "read_gen" ) or ( $propop eq "vary" ) )
	{
		( $names_ref, $newcontents_ref ) = read_gen_constraints ( \@constrainfiles, \%names, \%newcontents );
		%names = %$names_ref; #say TOFILE "OUT_PUT read_gen_constraints \%names " . dump( %names );
		%newcontents = %$newcontents_ref; #say TOFILE "OUT_PUT read_gen_constraints \%newcontents " . dump( %newcontents ); #UNUSED
	}
		
	if ( ( $propop eq "read_gen" ) or ( $propop eq "vary" ) )
	{
		foreach my $uniqnum ( sort { $a <=> $b } keys %nums )
		{
			foreach my $nickname ( keys %names )
			{
				if ( ( defined ( $nickname ) ) and ( $nickname ne "" ) )
				{
					if ( $nickname eq $nums{$uniqnum}{nickname} )
					{
						if ( ( $nums{$uniqnum}{newvalue} ne $names{$nickname}{newvalue} ) and ( $nums{$uniqnum}{newvalue} != $names{$nickname}{newvalue} ) )
						{
							$nums{$uniqnum}{newvalue} = $names{$nickname}{newvalue} ; #say TOFILE "IT HAPPENDED 2!";
						}
					}
				}
			}
		}
	} 
		
	#say TOFILE "BEFORE ENTERING: \%nums " . dump( %nums );
		
	sub foreachcontentsref
	{	#say TOFILE "ENTERED foreachcontentsref";
		my ( $plaincontents_ref, $names_ref, $nums_ref, $filecontents_ref ) = @_;
		my @plaincontents = @$plaincontents_ref;
		my %names = %$names_ref; #say TOFILE "BEFORE ENTERING: \%names " . dump( %names );
		my %nums = %$nums_ref; #say TOFILE "BEFORE ENTERING: \%nums " . dump( %nums );
		my @filecontents = @$filecontents_ref;
		my $countfile = 0;
		foreach my $fil ( @plaincontents )
		{
			my $countline = 0;
			#say TOFILE "\$countfile !: " . dump( $countfile );
			#say TOFILE "\@{ \$plaincontents[ \$countfile ] !: " . dump( @{ $plaincontents[ $countfile ] } );
			foreach my $newrow ( @$fil )
			{	#say TOFILE "\$newrow !: " . dump( $newrow ); say TOFILE "\$countline !: " . dump( $countline ); 	
				my $thisnewrow;
				foreach my $countunique ( sort { $a <=> $b } keys ( %nums ) )
				{				
					my $nickname = $nums{$countunique}{nickname}; #say TOFILE "WORKING ON \$nickname " . dump( $el );
					#say TOFILE "WORKINGON \$nickname " . dump( $nickname );
					my $el = $nums{$countunique}{oldvalue}; #say TOFILE "WORKING ON \$el " . dump( $el );
					my $newel = $nums{$countunique}{newvalue}; #say TOFILE "WORKING ON \$newel " . dump( $newel );
					my $countrow = $nums{$countunique}{countrow}; #say TOFILE "WORKING ON \$countrow " . dump( $countrow );
					my $countelt = $nums{$countunique}{countelt}; #say TOFILE "WORKING ON \$countelt " . dump( $countelt );
					my $fullfilepath = $nums{$countunique}{fullfilepath}; #say TOFILE "WORKING ON \$fullfilepath " . dump( $fullfilepath );
					my $separator = $nums{$countunique}{separator}; #say TOFILE "WORKING ON \$separator " . dump( $separator );
					my $counteltminus1 = ( $countelt - 1 );
					if ( defined( $newel ) and ( $newel ne "" ) and  defined( $el ) and ( $el ne "" ) and defined( $el ) and ( $el ne " " ) )
					{	
						if ( $countrow == $countline )
						{	#say TOFILE "WRITING HIT! ";
							my $alternewrow = $newrow;
							$alternewrow =~ s/^\s+//; # CLEAR WHITE SPACES AT THE BEGINNING OF THE LINE
							$alternewrow =~ s/\s+//g; #say TOFILE " IN \$alternewrow $alternewrow ";# MAKE SEQUENCES OF WHITE SPACES ONE SPACE
							my @rowelts = split( /\s+|,|;/, $alternewrow ); say TOFILE " IN \@rowelts @rowelts "; say TOFILE " IN \@rowelts @rowelts ";
							#my @rowelts = @{ $filecontents[ $countfile ][ $countline ] };
							#@rowelts = purifyarray( @rowelts );
							my $thiselt = $rowelts[ $countelt ]; #print  TOFILE "\$thiselt !: " . dump( $thiselt ); say TOFILE " IN \$countelt $countelt ";
							my @previouselts = @rowelts[ 0..$counteltminus1 ]; #say TOFILE "\@previouselts !: " . dump( @previouselts );			
							my $countscore = 0;
							foreach my $elem ( @previouselts )
							{
								my $elemcomma = "$elem,";
								my $elemcomma = "$thiselt,";
								if ( $elemcomma eq $thiselt )
								{
									$countscore++; #say TOFILE "\SCORE !: " . dump( $countscore );
								}
							}
							#say TOFILE "BEGUN WITH \$newrow !: " . dump( $newrow ); say TOFILE "\$el !: " . dump( $el ); say TOFILE "\$newel !: " . dump( $newel ); say TOFILE "\$countscore !: " . dump( $countscore ); 
							my ( $retel, $truenewel );
							if ( $tooltype eq "esp-r" )
							{
								( $retel, $truenewel ) = fixlength( $thiselt, $newel, "n" ); #ORIGINARY NUMBER, NEW NUMBER, "y" FOR ADJUSTING THE LENGTH DO THAT WHEN NEGATIVE IT OCCUPIES ONE CHARACTER MORE, or nothing 
								#say TOFILE "RETURNED FROM FIXLENGTH : \$retel !: " . dump( $retel ); say TOFILE "RETURNED FROM FIXLENGTH : \$truenewel !: " . dump( $truenewel );
								#say TOFILE "\$countrow : " . dump( $countrow ); say TOFILE "\$countelt : " . dump( $countelt );  say TOFILE "\$row WAS : " . dump( $newrow ); 
								$newrow = replace_nth( "$newrow", $countscore, "$retel,", "$truenewel," ); #say TOFILE "REDEFINED BY REPLACE NTH: \$newrow !: " . dump( $newrow );
							}
							else
							{	#say TOFILE "\$newel " . dump( $newel );
								#$newel = sprintf( "%.3f", $newel ); say TOFILE "\$newel " . dump( $newel );
								#say TOFILE "REPLACING $thiselt WITH $newel IN $newrow"; say TOFILE "\$fullfilepath $fullfilepath ";
								#$newrow = replace_nth( "$newrow", $countscore, "$thiselt,", "$newel," ); 
								#say TOFILE "OBTAINED_ $newrow"; say TOFILE "COUNTFILE2 : $countfile";
								$newel = sprintf( "%.3f", $newel ); #say TOFILE "\$newel " . dump( $newel );
								$rowelts[ $countelt ] = $newel; 
								my $begin = "  ";
								foreach ( @rowelts )
								{
									$begin = "$begin" . "$_" . "$separator ";
								}
								$newrow = "$begin\n"; #say TOFILE "NOWOBTAINED \$newrow " . dump( $newrow );
							}
						}
					}
				}	#say TOFILE "\$countfile : " . dump( $countfile ); #say TOFILE "\$countstep : " . dump( $countstep );
				$newfilecontents[ $countfile ][ $countline ] = $newrow ; #say TOFILE "PUSHING \$newrow $newrow";
				$countline++;
			}
			$countfile++;
		}
		return ( \@newfilecontents );
	}
	
	if ( ( $propop eq "read_gen" ) or ( $propop eq "vary" ) )
	{
		$newfilecontents_ref = foreachcontentsref ( \@plaincontents, \%names, \%nums, \@filecontents ); #say TOFILE "\$newfilecontents_ref : " . dump( $newfilecontents_ref );
		#say TOFILE "\$countfile : " . dump( $countfile ); say TOFILE "\$countstep : " . dump( $countstep );
		@newfilecontents = @$newfilecontents_ref; #say TOFILE "OUTPUT foreachcontentsref \@newfilecontents !: " . dump( @newfilecontents );
	}
				

	sub foreachfilerequest
	{	#say TOFILE "ENTERED foreachfilerequest";
		my ( $filequestions_ref, $to, $newfilecontents_ref ) = @_;
		my @filequestions = @$filequestions_ref; #say TOFILE "INPUTLAST \@filequestions " . dump( @filequestions );
		#say TOFILE "INPUTLAST  \$to " . dump( $to );
		my @newfilecontents = @$newfilecontents_ref; #say TOFILE "INPUTLAST \@newfilecontents " . dump( @newfilecontents );
		my $countfile = 0;
		foreach my $filequests ( @filequestions )
		{	#say TOFILE "2 \$countstep " . dump( $countstep );
			my @truequests = @$filequests; #say TOFILE "\@truequests " . dump( @truequests );	
			my $constrainfiles_ref = shift( @truequest );
			my @constrainfiles = @{ $constrainfiles_ref }; #say TOFILE "\@constrainfiles " . dump( @constrainfiles );
			my $thisfile = shift( @truequests );  #say TOFILE "\$thisfile " . dump( $thisfile ); say TOFILE "\@truequests " . dump( @truequests );
			my $fullfilepath = $to . $thisfile ; #say TOFILE "\$fullfilepath " . dump( $fullfilepath );
			my $new_fullfilepath = $fullfilepath . ".new" ; #say TOFILE "\$new_fullfilepath " . dump( $new_fullfilepath );
		
			my $oldfile = $fullfilepath . ".bac"; #say TOFILE "\$fullfilepath " . dump( $fullfilepath ); say TOFILE "\$oldfile " . dump( $oldfile );
			my $newfile = $fullfilepath . ".new"; #say TOFILE "\$newfile " . dump( $newfile );
			my $newfile_ = $to . ".idf"; #say TOFILE "\$newfile " . dump( $newfile );
			
			open( NEWFILECONTENTS, ">$newfile" ) or die( "$!" );
			#say TOFILE "COUNTFILE3 : $countfile";
			foreach my $my_row ( @{ $newfilecontents[ $countfile ] } )
			{
				if ( not ( ref( $my_row ) ) )
				{
					print NEWFILECONTENTS $my_row; #say TOFILE "PRINTING \$my_row " . dump( $my_row );
				}
			}
			close NEWFILECONTENTS;
			
			
			
			unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) )
			{
				say TOFILE "cp -f $fullfilepath $oldfile";
				`cp -f $fullfilepath $oldfile` ;
				say TOFILE "cp -f $newfile $fullfilepath";
				`cp -f $newfile $fullfilepath` ;
				say TOFILE "cp -f $newfile $newfile_";
				`cp -f $newfile $newfile_` ;
			}
			else
			{
				say TOFILE "xcopy  /e /c /r /y $fullfilepath $oldfile";
				`xcopy  /e /c /r /y $fullfilepath $oldfile`  or die ("$!") ;
				say TOFILE "xcopy  /e /c /r /y $newfile $fullfilepath";
				`xcopy  /e /c /r /y $newfile $fullfilepath` or die $! ;
				say TOFILE "xcopy  /e /c /r /y $newfile $newfile_";
				`xcopy  /e /c /r /y $newfile $newfile_` or die $! ;
			}
			$countfile++;
		}
	}
	
	if ( ( $propop eq "write_gen" ) or ( $propop eq "vary" ) )
	{
		foreachfilerequest( \@filequestions, $to, \@newfilecontents  );
	}
	close FULLFILEPATH;
	return ( \%names, \%nums, \%newcontents, \@filecontents, \@newfilecontents );
}


sub genprop
{	# TO DO: POSSIBILITY TO SPECIFY TEXT STRING IN PLACE OF ELEMENT
	#use strict; 
	#use warnings;
	#say TOFILE "IN GENCHANGE.";
	my ($to, $stepsvar, $countop, $countstep, $applytype_ref, $genchange, $countvar, $fileconfig, $mypath, $file, $countmorphing, $propop, 
		$names_ref, $nums_ref, $newcontents_ref, $filecontents_ref, $newfilecontents_ref, $launchline ) = @_;
	( $names_ref, $nums_ref, $newcontents_ref, $filecontents_ref, $newfilecontents_ref ) = genchange ($to, $stepsvar, $countop, $countstep, 
												$applytype_ref, $genchange, $countvar, $fileconfig, $mypath, $file, $countmorphing, $to_do,
												$names_ref, $nums_ref, $newcontents_ref, $filecontents_ref, $newfilecontents_ref, 
												$launchline );
	%names = %$names_ref;
	%newcontents = %$newcontents_ref;
	@filecontents = @$filecontents_ref;
	@newfilecontents = @$newfilecontents_ref;
	return ( \%names, \%newcontents, \@filecontents, \@newfilecontents );
}

sub change_groundreflectance
{
	#use strict; 
	#use warnings;
	( $to, $stepsvar, $countop, $countstep, $applytype_ref, $change_groundreflectance, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	my @applytype = @$applytype_ref; #say TOFILE "\@applytype : " . dump( @applytype );
	say $tee "Changing ground reflectance for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	my ( $low, $high, $swing, $pace, $newvalue );
	
	if ( $change_groundreflectance )
	{
		my @this_cycledata = @{ $change_groundreflectance->[ $countop ] }; #say TOFILE "\@this_cycledata : " . dump( @this_cycledata );
		my $basevalue = $this_cycledata[0]; #say TOFILE "\$basevalue : " . dump( $basevalue );
		my $swingcontent = $this_cycledata[1]; #say TOFILE "\$swingcontent : " . dump( $swingcontent );
		if ( ref( $swingcontent ) )
		{
			$low = $swingcontent->[0]; #say TOFILE "\$low : " . dump( $low );
			$high = $swingcontent->[1]; #say TOFILE "\$high : " . dump( $high );
			$swing = ( $high - $low ); #say TOFILE "\$swingA : " . dump( $swing );
		}
		else
		{
			$swing = ( $swingcontent * 2 ); #say TOFILE "\$swingB : " . dump( $swing );
		}
		$pace = ( $swing / ( $stepsvar - 1 ) ); #say TOFILE "\$pace : " . dump( $pace );
		$newvalue = ( $basevalue + ( $pace * ( $countstep - 1 ) ) ); #say TOFILE "\$newvalue : " . dump( $newvalue );
	}
	
	my $printthis =
"prj $launchline<<YYY

m
b
d
a
$newvalue
-
-
-
YYY
";

	unless ($exeonfiles eq "n") 
	{ 
		print `$printthis`;
	}
	print $tee "CHANGING GROUND REFLECTANCE.\n
$printthis
";
	#no strict; 
	#no warnings;
}

##############################################################################
# SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING GEOMETRY

sub constrain_geometry # IT APPLIES CONSTRAINTS TO ZONE GEOMETRY
{
	# IT CONSTRAINS GEOMETRY FILES.
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $constrain_geometry_ref, $countvar, $fileconfig, $v_ref, $countmorphing, $exeonfiles, $v__ref, $propop, $launchline ) = @_;
	say $tee "Constraining geometry for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @applytype = @$applytype_ref; #say TOFILE "INMAIN \@applytype : " . dump( @applytype );
	my $zone_letter = $applytype[$countop][3]; #say TOFILE "\$zone_letter : " . dump( $zone_letter );
	
	#say TOFILE "\@\$constrain_geometry_ref : " . dump( @$constrain_geometry_ref );
	my @constrain_geometry = @{ $constrain_geometry_ref->[$countop] }; #say TOFILE "\@constrain_geometry[\$countop] : " . dump( @constrain_geometry );
	
	my @v = @$v_ref; #say TOFILE "\@v : " . dump( @v );
	my @v_ = @v__ref;
	
	my @vertexletters = (
	"a", 	"b", 	"c", 	"d", 	"e", 	"f", 	"g", 	"h", 	"i", 	"j", 	"k", 	"l", 	"m", 	"n", 	"o", 	"p", 
	"0\np", "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\nc",	"0\nd",	"0\ne",
	"0\n0\nb\ne", "0\n0\nb\nf", "0\n0\nb\ng", "0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", 
	"0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", "0\n0\nb\ns", "0\n0\nb\nt", 
	"0\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", 
	"0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", 
	"0\n0\nb\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\n0\nb\nj", "0\n0\nb\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\n0\nb\np", 
	"0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx"
	);

	say $tee "Propagating constraints on geometry for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	my $countopplus1 = ( $countop + 1 ); #say TOFILE "\$countopplus1 : " . dump( $countopplus1 );

	my $countelm = 0;
	foreach my $elm ( @constrain_geometry )
	{
		#say TOFILE "IN LOOP";
		my $countelmplus1 = ( $countelm + 1 ); #say TOFILE "\$countelmplus1 : " . dump( $countelmplus1 );
		my @group = @{ $elm }; #say TOFILE "\@group : " . dump( @group );
		my $zone_letter = $group[0]; #say TOFILE "\$zone_letter : " . dump( $zone_letter );
		my $sourcefile = $group[1]; #say TOFILE "\$sourcefile : " . dump( $sourcefile );
		my $targetfile = $group[2]; #say TOFILE "\$targetfile : " . dump( $targetfile );
		my $configfile = $group[3]; #say TOFILE "\$configfile : " . dump( $configfile );
		my @work_letters = @{$group[4]};  #say TOFILE "\@work_letters : " . dump( @work_letters );
		my @swings__ = @{ $group[5] }; #say TOFILE "\@swings__ : " . dump( @swings__ );
		my $askop = $group[6]; #say TOFILE "\$askop : " . dump( $askop );
		unless ( $askop ) { $askop = 0; } #say TOFILE "\$askop : " . dump( $askop );
		
		my $sourceaddress = "$to$sourcefile"; #say TOFILE "\$sourceaddress : " . dump( $sourceaddress );
		my $targetaddress = "$to$targetfile"; #say TOFILE "\$targetaddress : " . dump( $targetaddress );
		
		my $configaddress;
		unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
		{
			$configaddress = "$mypath/$configfile"; #say TOFILE "\$configaddress : " . dump( $configaddress );
		}
		else
		{
			$configaddress = "$mypath\\$configfile"; #say TOFILE "\$configaddress : " . dump( $configaddress );
		}
		
		
		my ( @work_items, @swings, @paces );
		
		foreach ( @swings__ )
		{
			if ( ref ( $_ ) )
			{
				$_ = ( $_->[0] - $_->[1] );
			}
			else
			{
				$_ = ( $_ * 2 );
			}
			push ( @swings, $_ );
		} say TOFILE "\@swings : " . dump( @swings );
		
		foreach ( @swings )
		{
			my $pace = ( $_ / ( $stepsvar - 1 ) );
			push ( @paces, $pace );
		} #say TOFILE "\@paces : " . dump( @paces );
		
		if ( $propop eq "read_geo")
		{
			checkfile( $sourceaddress, $targetaddress );
			@v = read_geometry( $sourceaddress, $countopplus1, $countelmplus1, $zone_letter, $sourceaddress, $targetaddress, $launchline );
			@v_  = read_geo_constraints( $to, $fileconfig, $stepsvar, $countopplus1, $countstep, $configaddress, 
							\@v, $countvar, \@swings, \@paces, $zone_letter, $sourceaddress, $targetaddress, 
							$countmorphing, $countelmplus1, $launchline );
		}

		if ($propop eq "write_geo")
		{
			apply_geo_constraints( \@v, \@v_, \@vertexletters, \@work_letters, $exeonfiles, $zone_letter, $sourceaddress, 
						$targetaddress, $countopplus1, $countelmplus1, $askop, $to, $launchline );
		} 
		$countelm++;
	}  #say TOFILE "RESTITUTING \@v_ : " . dump( @v_ ); 
	return ( \@v, \@v_ );
} # END SUB constrain_geometry


sub read_geometry # THIS READS GEOMETRY FILES TO GET THE VERTICES.
{
	my ( $sourceaddress, $countopplus1, $countelmplus1, $zone_letter, $sourceaddress, $targetaddress, $launchline ) = @_;
	say $tee "Reading geometry for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
		
	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourcefile 2: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;

	my $countlines = 0;
	my $countvert = 1;
	#say TOFILE "INREAD";
	foreach my $line (@lines)
	{
		$line =~ s/^\s+//; #say TOFILE "\$line : " . dump( $line );

		my @rowelements = split(/\s+|,/, $line); #say TOFILE "\@rowelements : " . dump( @rowelements );
		if   ( $rowelements[0] eq "*vertex" ) 
		{
			$v[ $countopplus1 ][ $countelmplus1 ][ $countvert ] = [ $rowelements[1], $rowelements[2], $rowelements[3] ];
			$countvert++; #say TOFILE "READING \$rowelements[1] : " . dump( $rowelements[1] ); say TOFILE "\$rowelements[2] : " . dump( $rowelements[2] ); say TOFILE "\$rowelements[3] : " . dump( $rowelements[3] );
		}
		$v[ $countopplus1 ][ $countelmplus1 ][ 0 ] = "source: $sourceaddress zone: $zone_letter sourceaddress: $sourceaddress targetaddress: $targetaddress ";
		$countlines++;
	}
	#say TOFILE "\@v : " . dump( @v );
	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_[sequence_of_operation_numbers][operations_number][x_variable_number][$x], $v_[sequence_of_operation_numbers][operations_number][y_variable_number][$y],
	# $v_[operations_number][z_variable_number][$z]. 
	# EXAMPLE: $v_[1][1][4][\$x] = 1. OR: @v_[1][2][4][\$x] = @v_[1][2][4][\$y]. OR: @v_[1][1][4][\$x] = @v_[1][2][3][\$z].
	# sequence_of_operation_numbers and operation_numbers number mutations in parallel.
	# PROPAGATION OF CONSTRAINTS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO VARIABLES. 
	# BESIDES THE VARIABLES FOR THE VERTICES, THE FOLLOWING VARIABLES ARE ALWAYS AVAILABLE: 
	# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
	# $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, $countopplus1, $countstep, $configaddress, 
		$v_ref, $countvar, $swings_ref, $paces_ref, $zone_letter, $sourceaddress, $targetaddress, $countmorphing, $countelmplus1, $launchline ) = @_;
	say $tee "Reading geometric constraints for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @v = @$v_ref; #say TOFILE "\INREADCONSTRAINTS"; #say TOFILE "TAKEN \@v : " . dump( @v );
	my $v_ = dclone($v_ref); 
	my @v_ = @$v_; #say TOFILE "TAKEN \@v_ : " . dump( @v_ );
	 
	my @swings = @$swings_ref; #say TOFILE "\@swings : " . dump( @swings );
	my @paces = @$paces_ref; #say TOFILE "\@paces : " . dump( @paces );
	my @truev;

	$x = 0;
	$y = 1;
	$z = 2;

	if ( defined ( $configaddress ) )
	{
		if ( -e $configaddress )
		{	
			eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED.
		} 
		else 
		{
			say $tee "\$configaddress does not exist. Exiting." and die;
		}
	}
	#say TOFILE "BEFORE PURIFICATION \@v : " . dump( @v );
	#say TOFILE "BEFORE PURIFICATION \@v_ : " . dump( @v_ );
	$v_[ $countopplus1 ][ $countelmplus1 ] = purifydata( \@{ $v[ $countopplus1 ][ $countelmplus1 ] } , \@{ $v_[ $countopplus1 ][ $countelmplus1 ] } );
	#say TOFILE "AFTER PURIFICATION \@{ \$v_[ \$countopplus1 ][ \$countelmplus1 ] } : " . dump( @{ $v_[ $countopplus1 ][ $countelmplus1 ] } );
	return ( @v_ );
} # END SUB read_geo_constraints


sub apply_geo_constraints
{
	my ( $v_ref, $v__ref, $vertexletters_ref, $work_letters_ref, $exeonfiles, $zone_letter, $sourceaddress, 
						$targetaddress, $countopplus1, $countelmplus1, $askop, $to, $launchline ) = @_;
	
	#say TOFILE "INAPPLY";
	my @v = @$v_ref; #say TOFILE "\@v : " . dump( @v );
	my @v_ = @$v__ref; #say TOFILE "\@v_ : " . dump( @v_ );
	#say TOFILE "\$countopplus1 : " . dump( $countopplus1 );say TOFILE "\$countelmplus1 : " . dump( $countelmplus1 );
	my @vertexletters = @$vertexletters_ref; #say TOFILE "\@vertexletters : " . dump( @vertexletters );
	my @work_letters = @$work_letters_ref; #say TOFILE "\@work_letters : " . dump( @work_letters );

	#say TOFILE "CHECK1 \@{ \$v_[ \$countopplus1 ][ \$countelmplus1 ] } : " . dump( @{ $v_[ $countopplus1 ][ $countelmplus1 ] } );
	#say TOFILE "CHECK2 \@{ \$v_->[ \$countopplus1 ][ \$countelmplus1 ] } : " . dump( @{ $v_->[ $countopplus1 ][ $countelmplus1 ] } );
	#say TOFILE "CHECK3 \$v_[ \$countopplus1 ][ \$countelmplus1 ] : " . dump( $v_[ $countopplus1 ][ $countelmplus1 ] );
	#say TOFILE "CHECK4 \$v_->[ \$countopplus1 ][ \$countelmplus1 ] : " . dump( $v_->[ $countopplus1 ][ $countelmplus1 ] );
	my $countvertex = 0; 
	foreach my $v_ ( @{ $v_[ $countopplus1 ][ $countelmplus1 ] } )
	{	#say TOFILE "\$v_ : " . dump( $v_ ); say TOFILE "\$v : " . dump( $v );
		my $v = $v[ $countopplus1 ][ $countelmplus1 ][ $countvertex ];
		my $vertexletter = $vertexletters[$countvertex];
		
		my $countv = 0;
		my $diffq = 0;
		foreach ( @$v )
		{	#say TOFILE "HEREDO \$v_->[\$countv] : " . dump( $v_->[$countv] );
			if ( ( $v_->[$countv] != $v->[$countv]  ) and ( $v_->[$countv] ne $v->[$countv] ) )
			{	#say TOFILE "\HIT";
				$v_->[$countv] = fixlength( $v->[$countv] , $v_->[$countv] );
				$diffq++;
			}
			$countv++;
		}
		
		if ( ( ( @work_letters eq "" ) or ( $vertexletter  ~~ @work_letters ) or ( not ( defined( @work_letters ) ) ) ) and ( ( not ( $v_ =~ /^target/ ) ) or ( not ( $v_ =~ /^source/ ) ) ) and ( $diffq > 0 ) ) 
		{ 
			my $printthis =
"prj $launchline<<YYY

m
c
a
$zone_letter
d
$vertexletter
$v_->[0] $v_->[1] $v_->[2]
-
y
-
y
c
-
-
-
-
-
-
-
-
-
YYY
";
			unless ($exeonfiles eq "n") 
			{
				print `$printthis`;
			}

			print TOFILE $printthis;
		}
		$countvertex++;
	}

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


##############################################################################
# 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, $applytype_ref, $constrain_obstructions_ref, $countvar, $fileconfig, 
		$countmorphing, $exeonfiles, $obs_ref, $obs__ref, $propop, $launchline ) = @_;
	
	my @applytype = @$applytype_ref;
	my @obs = @$obs_ref;
	my @obs_ = @$obs__ref;
	my $zone_letter = $applytype[$countop][3]; #say TOFILE "\$zone_letter : " . dump( $zone_letter );
	#say TOFILE "\$constrain_obstructions_ref : " . dump( $constrain_obstructions_ref );
	#say TOFILE "\$countop : " . dump( $countop );
	my @constrain_obstructions = @{ $constrain_obstructions_ref->[ $countop ] }; #say TOFILE "\@constrain_obstructions : " . dump( @constrain_obstructions );
	
	say $tee "Propagating constraints on obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my ( @work_letters );
	
	my $countopplus1 = ( $countop + 1 ); #say TOFILE "\$countopplus1 : " . dump( $countopplus1 );
	my $countelm = 0;
	foreach my $elm (@constrain_obstructions)
	{
		my $countelmplus1 = ( $countelm + 1 ); #say TOFILE "\$countelmplus1 : " . dump( $countelmplus1 );
		my @group = @{$elm}; #say TOFILE "\@group : " . dump( @group );
		my $zone_letter = $group[0]; #say TOFILE "\$zone_letter : " . dump( $zone_letter );
		my $sourcefile = $group[1]; #say TOFILE "\$sourcefile : " . dump( $sourcefile );
		my $targetfile = $group[2]; #say TOFILE "\$targetfile : " . dump( $targetfile );
		my $configfile = $group[3]; #say TOFILE "\$configfile : " . dump( $configfile );
		my @work_letters = @{$group[4]};  #say TOFILE "\@work_letters : " . dump( @work_letters );
		my @swings__ = @{ $group[5] }; #say TOFILE "\@swings__ : " . dump( @swings__ );
		my $actonmaterials = $group[6]; #say TOFILE "\$actonmaterials : " . dump( $actonmaterials );
		my @matobs_letters = @{$group[7]}; #say TOFILE "\@matobs_letters : " . dump( @matobs_letters );
		my ( @swings, @paces ); 
		
		my $sourceaddress = "$to$sourcefile"; #say TOFILE "\$sourceaddress : " . dump( $sourceaddress );
		my $targetaddress = "$to$targetfile"; #say TOFILE "\$targetaddress : " . dump( $targetaddress );
		
		my $configaddress;
		unless ( ( "$^O" eq "MSWin32" ) or ( "$^O" eq "MSWin64" ) ) 
		{		
			$configaddress = "$mypath/$configfile"; #say TOFILE "\$configaddress : " . dump( $configaddress );
		}
		else
		{		
			$configaddress = "$mypath\\$configfile"; #say TOFILE "\$configaddress : " . dump( $configaddress );
		}
		
		my @obs_letters = (
		"e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", 
		"0\no", "0\np", "0\nq", "0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", "0\ny", 
		"0\n0\nb\ny", "0\n0\nb\nz", "0\n0\nb\na", "0\n0\nb\nb", "0\n0\nb\nc", "0\n0\nb\nd", "0\n0\nb\ne", "0\n0\nb\nf", "0\n0\nb\ng", "0\n0\nb\nh", "0\n0\nb\ni",
		"0\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\nj", "0\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\nn", 
		"0\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\np", "0\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\ns", 
		"0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nvs", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx", 
		"0\n0\nb\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\n0\nb\nc", 
		);
		
		foreach ( @swings__ )
		{
			if ( ref ( $_ ) )
			{
				$_ = ( $_->[0] - $_->[1] );
			}
			else
			{
				$_ = ( $_ * 2 );
			}
			push ( @swings, $_ );
		} #say TOFILE "\@swings : " . dump( @swings );
		
		foreach ( @swings )
		{
			my $pace = ( $_ / ( $stepsvar - 1 ) );
			push ( @paces, $pace );
		} #say TOFILE "\@paces : " . dump( @paces );
		
		if ($propop eq "read_obs")
		{
			#say TOFILE "GOING TO READ";
			checkfile( $sourceaddress, $targetaddress );
			@obs = read_obstructions( $to, $sourceaddress, $targetaddress, $countopplus1, $countelmplus1, $zone_letter, $configaddress, 
							\@work_letters, $actonmaterials, $countvar, \@obs_letters, $countmorphing, $launchline );
			@obs_ = read_obs_constraints( $to, $stepsvar, $countop, $countstep, $configaddress, $actonmaterials, $countvar, $fileconfig, $countmorphing,
				$countopplus1, \@obs, \@swings, \@paces, $zone_letter, $sourceaddress, $targetaddress, $countelmplus1, $launchline ); # IT WORKS ON THE VARIABLE @obs, WHICH IS globsAL.
		}

		if ($propop eq "write_obs")
		{
			#say TOFILE "GOING TO WRITE";
			apply_obs_constraints( \@obs, \@obs_, \@obs_letters, \@work_letters, $zone_letter, $actonmaterials, \@vertexletters, 
						$exeonfiles,  $sourceaddress, $targetaddress, $countopplus1, $countelmplus1, $to, $launchline );
		} 
		$countelm++;
	} #say TOFILE "RESTITUTING \@obs_ : " . dump( @obs_ ); #say TOFILE "\@obs_ : " . dump( @obs_ );
	return ( \@obs, \@obs_ );
} # 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, $countopplus1, $countelmplus1, $zone_letter, $configaddress, $work_letters_ref, 
		$actonmaterials, $countvar, $obs_letters_ref, $countmorphing, $launchline ) = @_;
	say $tee "Reading obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	my @work_letters = @$work_letters_ref;
				
	open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourceaddress: $!\n";
	my @lines = <SOURCEFILE>;
	close SOURCEFILE;

	my $countobs = 0;
	foreach my $line (@lines)
	{
		$line =~ s/^\s+//; 
		my @rowelts = split(/\s+|,/, $line); #say TOFILE "\@rowelements : " . dump( @rowelements );
		if  ( $rowelts[0] eq "*obs" ) 
		{
			$obs[ $countopplus1 ][ $countelmplus1 ][ $countobs ] = [ "*obs", $rowelts[1], $rowelts[2], $rowelts[3] , $rowelts[4], $rowelts[5], $rowelts[6], $rowelts[7], 
			$rowelts[8], $rowelts[9], $rowelts[10], "#", "block", $rowelts[13] ];
			$countobs++;
		}
		$obs[ $countopplus1 ][ $countelmplus1 ][ 0 ] = "source: $sourceaddress zone: $zone_letter sourceaddress: $sourceaddress targetaddress: $targetaddress ";
	}
	#say TOFILE "\@obs : " . dump( @obs );
	return( @obs );
} # 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][$countelm][$obs_number][$x], $obs[$countop][$obs_number][$y], $obs[$countop][$obs_number][$z]
	# $obs[$countop][$countelm][$obs_number][$width], $obs[$countop][$obs_number][$depth], $obs[$countop][$obs_number][$height]
	# $obs[$countop][$countelm][$obs_number][$z_rotation], $obs[$countop][$obs_number][$y_rotation], 
	# $obs[$countop][$countelm][$obs_number][$tilt], $obs[$countop][$obs_number][$opacity], $obs[$countop][$obs_number][$material], 
	# EXAMPLE: $obs[0][1][2][$x] = 2. 
	# OTHER EXAMPLE: $obs[0][1][2][$x] = $obs[2][2][2][$y].
	# THE MATERIAL TO BE SPECIFIED IS A MATERIAL LETTER, BETWEEN QUOTES. EXAMPLE: $obs[1][$material] = "a".
	# sequence_of_operation_numbers and operation_numbers number mutations in parallel.
	# PROPAGATION OF CONSTRAINTS ALLOWS TO IMPOSE EQUALITY CONSTRAINTS TO VARIABLES. 
	# BESIDES THE VARIABLES FOR THE VERTICES, THE FOLLOWING VARIABLES ARE ALWAYS AVAILABLE:
	# $stepsvar, WHICH TELLS THE PROGRAM HOW MANY ITERATION STEPS IT HAS TO DO IN THE CURRENT MORPHING PHASE.
	# $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, $countvar, $fileconfig, $countmorphing,
		$countopplus1, $obs_ref, $swings_ref, $paces_ref, $zone_letter, $sourceaddress, $targetaddress, $countelmplus1, $launchline ) = @_;
	my @obs = @$obs_ref;
	my $obs__ref = dclone( $obs_ref );  
	my @obs_ = @$obs__ref;
	my @swings = @$swings_ref;
	my @paces = @$paces_ref;
	
	say $tee "Reading geometric constraints for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $x = 1;
	my $y = 2;
	my $z = 3;
	my $width = 4;
	my $depth = 5;
	my $height = 6;
	my $zrotation = 7;
	my $yrotation = 8;
	my $tilt = 9; # UNUSED
	my $opacity = 10;
	my $name = 11; # NOT TO BE CHANGED
	my $material = 12;
	my $number = 15;
 
	if ( defined ( $configaddress ) )
	{
		if (-e $configaddress)
		{		
			eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED.
		}
		else 
		{
			say TOFILE "\$configaddress does not exist. Exiting." and die;
		}
	}
	#say TOFILE "BEFORE PURIFICATION \@obs : " . dump( @obs );
	#say TOFILE "BEFORE PURIFICATION \@obs_ : " . dump( @obs_ );
	$obs_[ $countopplus1 ][ $countelmplus1 ] = purifydata( \@{ $obs[ $countopplus1 ][ $countelmplus1 ] } , \@{ $obs_[ $countopplus1 ][ $countelmplus1 ] } );
	#say TOFILE "AFTER PURIFICATION \@{ \$obs_[ \$countopplus1 ][ \$countelmplus1 ] } : " . dump( @{ $obs_[ $countopplus1 ][ $countelmplus1 ] }  );
	return ( @obs_ );
} # END SUB read_geo_constraints


sub apply_obs_constraints
{
	my ( $obs_ref, $obs__ref, $obs_letters_ref, $work_letters_ref, $zone_letter, $actonmaterials, $vertexletters_ref, 
		$exeonfiles,  $sourceaddress, $targetaddress, $countopplus1, $countelmplus1, $to, $launchline ) = @_;
	say $tee "Constraining obstructions for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";
	
	my @obs = @$obs_ref; #say TOFILE "PREPARING \@obs : " . dump( @obs );
	my @obs_ = @$obs__ref; #say TOFILE "\@obs_ : " . dump( @obs_ );	#say TOFILE "\$countopplus1 : " . dump( $countopplus1 ); #say TOFILE "\$countelmplus1 : " . dump( $countelmplus1 );
	my @obs_letters = @$obs_letters_ref; #say TOFILE "\@obs_letters : " . dump( @obs_letters );
	my @work_letters = @$work_letters_ref; #say TOFILE "\@work_letters : " . dump( @work_letters );
	
	#print TOFILE "OBS_LETTERS IN APPLY" . Dumper(@obs_letters) . "\n\n"; #say TOFILE "\@{ \$obs_[ \$countopplus1 ][ \$countelmplus1 ] } : " . dump( @{ $obs_[ $countopplus1 ][ $countelmplus1 ] } );
	
	my $countobs = 0;
	foreach my $ob_ ( @{ $obs_[ $countopplus1 ][ $countelmplus1 ] } )
	{
		#say TOFILE "INSPECTING: \$ob_ : " . dump( $ob_ );
		my $ob = $obs[ $countopplus1 ][ $countelmplus1 ][ $countobs ]; #say TOFILE "\$ob : " . dump( $ob );
		my $obs_letter = $obs_letters[ $countobs ]; #say TOFILE "\$obs_letter : " . dump( $obs_letter );
		
		my $diffq = 0;
		my $countelt = 0;
		foreach ( @$ob_ )
		{
			if ( ( $ob_->[ $countelt ] != $ob->[ $countelt ] ) and ( $ob_->[ $countelt ] ne $ob->[ $countelt ] ) )
			{
				$ob_->[ $countelt ] = fixlength( $ob->[ $countelt ], $ob_->[ $countelt ] ); #say TOFILE "YES, \@ob_ equal \@ob : " . dump( @ob_ ) . " equal " . dump( @ob );
				$diffq++;
			}
			$countelt++;
		} #say TOFILE "MAY DO";
		if ( ( ( @work_letters eq "" ) or ( $obs_letter  ~~ @work_letters ) or ( not ( defined( @work_letters ) ) ) ) and ( ( not ( $v_ =~ /^target/ ) ) or ( not ( $v_ =~ /^source/ ) ) )  and ( $diffq > 0 ) )
		{	#say TOFILE "DOING";
			my $x = $ob_->[1];
			my $y = $ob_->[2];
			my $z = $ob_->[3];
			my $width = $ob_->[4];
			my $depth = $ob_->[5];
			my $height = $ob_->[6];
			my $z_rotation = $ob_->[7];
			my $y_rotation = $ob_->[8];
			my $opacity = $ob_->[9];
			my $name = $ob_->[10];
			my $material = $ob_->[11];
			my $number = $ob_->[14];
			my $printthis =
"prj $launchline<<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
h
$opacity
-
-
c
-
c
-
-
-
-
YYY
";
			unless ($exeonfiles eq "n") 
			{
				print `$printthis`;
			}

			print TOFILE $printthis;

			if ($actonmaterials eq "y")
			{	my $thismaterial = $material->[ $countstep -1 ];
				my $printthis =
"prj $launchline<<YYY

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

				print TOFILE $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 read_net # MAINTAIN ZZZ
{
	say "Reading networks for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my ( $sourceaddress, $targetaddress, $node_letters_ref, $component_letters_ref, $countvar, $countmorphing, $launchline ) = @_;
	
	# checkfile($sourceaddress, $targetaddress); # THIS HAS TO BE _FIXED!_
	my @node_letters = @$node_letters_ref;
	my @component_letters = @$component_letters_ref;

	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++;
	}
	return ( \@node, \@component );
} # 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 ) = @_;
	say "Applying changes to network nodes for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	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
";
				unless ($exeonfiles eq "n") 
				{
					print `$printthis`;
				}
				print TOFILE $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
";
				unless ($exeonfiles eq "n") 
				{
					print `$printthis`;
				}
				print TOFILE $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 ) = @_;
	say "Applying changes to network components for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	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
";
				unless ($exeonfiles eq "n") 
				{
					print `$printthis`;
				}
				print TOFILE $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
";
				unless ($exeonfiles eq "n") 
				{
					print `$printthis`;
				}
				print TOFILE $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
";
				unless ($exeonfiles eq "n") 
				{
					print `$printthis`;
				}
				print TOFILE "$printthis";
			}
		}
		$countcomponent++;
	}
} # END SUB apply_component_changes;


sub constrain_net 
{	# IT ALLOWS TO MANIPULATE USER-IMPOSED CONSTRAINTS REGARDING NETS
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $constrain_net_ref, $countvar, $fileconfig, $countmorphing, $propop, 
		$node_ref, $component_ref, $donode_ref, $docomponent_ref, $launchline  ) = @_;
	say "Constraining network for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my @applytype = @$applytype_ref;
	my @node = @$node_ref;
	my @component = @$component_ref;
	my @donode = @$donode_ref;
	my @docomponent = @$docomponent_ref;
											
	my $zone_letter = $applytype[$countop][3];
	my @constrain_net = @{ $constrain_net_ref[ $countop ] };
	
	my $elm = $constrain_net[$countop];
	
	my @node_letters = ( 
	"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", 
	"0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", "0\ny", "0\nz", "0\nz", "0\na", "0\nb", "0\nc", "0\nd", "0\ne", "0\nf",	"0\ng", "0\nh", 
	"0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", "0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", 
	"0\n0\nb\ns", "0\n0\nb\nt", "0\n0\nb\nu", "0\n0\nb\nv", "0\n0\nb\nw", "0\n0\nb\nx", "0\n0\nb\ny",
	"0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\nj", 
	"0\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\np", 
	"0\n0\nb\n0\nb\n0\nb\np", "0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\n0\nb\nb", 
	"0\n0\nb\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\n0\nb\ng"
	); # RE-CHECK
	
	my @component_letters = (
	"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", 
	"0\nr", "0\ns", "0\nt", "0\nu", "0\nv", "0\nw", "0\nx", "0\ny", "0\nz", "0\nz", "0\na", "0\nb", "0\nc", "0\nd", "0\ne", "0\nf",	"0\ng", "0\nh", 
	"0\n0\nb\nh", "0\n0\nb\ni", "0\n0\nb\nj", "0\n0\nb\nk", "0\n0\nb\nl", "0\n0\nb\nm", "0\n0\nb\nn", "0\n0\nb\no", "0\n0\nb\np", "0\n0\nb\nq", "0\n0\nb\nr", 
	"0\n0\nb\ns", "0\n0\nb\nt", "0\n0\nb\nu", "0\n0\nb\nv", "0\n0\nb\nw", "0\n0\nb\nx", "0\n0\nb\ny",
	"0\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\nb", "0\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\ng", "0\n0\nb\n0\nb\nh", "0\n0\nb\n0\nb\ni", "0\n0\nb\n0\nb\nj", 
	"0\n0\nb\n0\nb\nk", "0\n0\nb\n0\nb\nl", "0\n0\nb\n0\nb\nm", "0\n0\nb\n0\nb\nn", "0\n0\nb\n0\nb\no", "0\n0\nb\n0\nb\np", 
	"0\n0\nb\n0\nb\n0\nb\np", "0\n0\nb\n0\nb\n0\nb\nq", "0\n0\nb\n0\nb\n0\nb\nr", "0\n0\nb\n0\nb\n0\nb\ns", "0\n0\nb\n0\nb\n0\nb\nt", "0\n0\nb\n0\nb\n0\nb\nu", "0\n0\nb\n0\nb\n0\nb\nv", "0\n0\nb\n0\nb\n0\nb\nw", "0\n0\nb\n0\nb\n0\nb\nx", "0\n0\nb\n0\nb\n0\nb\ny", "0\n0\nb\n0\nb\n0\nb\nz", "0\n0\nb\n0\nb\n0\nb\na", "0\n0\nb\n0\nb\n0\nb\nb", 
	"0\n0\nb\n0\nb\n0\nb\nc", "0\n0\nb\n0\nb\n0\nb\nd", "0\n0\nb\n0\nb\n0\nb\ne", "0\n0\nb\n0\nb\n0\nb\nf", "0\n0\nb\n0\nb\n0\nb\ng"
	); # RE-CHECK
		
	my $countopplus1 = ( $countop + 1 );
	
	my $countelt = 0;
	foreach my $elt ( @$elm )
	{
		my $counteltplus1 = ( $countelt + 1 );
		
		my @group = @$elt;
		my $sourcefile = $group[0];
		my $targetfile = $group[1];
		my $configfile = $group[2];
		my @nodebulk = @{$group[3]};
		my @componentbulk = @{$group[4]};
		my $sourceaddress = "$to$sourcefile"; #say TOFILE "\$sourceaddress : " . dump( $sourceaddress );
		my $targetaddress = "$to$targetfile"; #say TOFILE "\$targetaddress : " . dump( $targetaddress );
		my $configaddress = "$mypath/$configfile"; #say TOFILE "\$configaddress : " . dump( $configaddress );

		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 $countnode = 0;
		my $countcomponent = 0;

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

		if ($propop eq "read_net")
		{
			checkfile($sourceaddress, $targetaddress);
			if ($countstep == 1)
			{
				( $node_ref, $component_ref ) = read_net($sourceaddress, $targetaddress, \@node_letters, \@component_letters);
				( $donode_ref, $docomponent_ref ) = read_net_constraints
				($to, $stepsvar, $countop, $countstep, $configaddress, \@node, \@component, \@tempnode, \@tempcomponent, $countvar, $fileconfig, $countmorphing  ); # PLURAL
			}
		}
		
		@node = @$node_ref;
		@component = @$component_ref;
		@donode = @$donode_ref;
		@docomponent = @$docomponent_ref;
		
		if ($propop eq "write_net")
		{
			apply_node_changes( \@donode, \@tempnode ); #PLURAL
			apply_component_changes( \@docomponent, \@tempcomponent );
		}
		$countelt++;
	}
	return ( \@node, \@component, \@donode, \@docomponent );
} # END SUB constrain_net.


sub read_net_constraints
{
	my ( $to, $stepsvar, $countop, $countstep, $configaddress, $swap, $swap2, $swap3, $swap4, $countvar, $fileconfig, $countmorphing ) = @_;
	
	@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. THE NUMBER COUNT STARTS FROM 0.
		# $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 );
	}
	return( \@donode, \@docomponent );
} # END SUB read_net_constraints
##############################################################################
# END OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING MASS-FLOW NETWORKS


sub vary_controls
{  	# IT IS CALLED FROM THE MAIN FILE
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $vary_controls_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing, $launchline ) = @_;
	
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @vary_controls = @{ $vary_controls_ref[ $countop ] } ;
	
	say "Variating 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, $countmorphing ) = @_;
		
		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
	
	calc_newctl($to, $stepsvar, $countop, $countstep, \@buildbulk, 
	\@flowbulk, \@loopcontrol, \@flowcontrol, $countvar, $fileconfig );

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

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

} # END SUB vary_controls.


##############################################################################
# BEGINNING OF SECTION DEDICATED TO FUNCTIONS FOR CONSTRAINING CONTROLS

sub constrain_controls 
{	# IT READS CONTROL USER-IMPOSED CONSTRAINTS
	my ( $to, $filecon, $countop, $countstep, $applytype_ref, $constrain_controls_ref, $countvar, $fileconfig, $countmorphing, $propop, 
		$loopcontrol_ref, $flowcontrol_ref, $new_loopcontrol_ref, $new_flowcontrol_ref, $launchline ) = @_;
	say "Constraining controls for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	my $zone_letter = $applytype[$countop][3];
	my @applytype = @$applytype_ref;
	my @constrain_controls = @{ $constrain_controls_ref[ $countop ] };
	my @loopcontrol = @$loopcontrol_ref;
	my @flowcontrol = @$flowcontrol_ref;
	my @new_loopcontrol = @$new_loopcontrol_ref;
	my @new_flowcontrol = @$new_flowcontrol_ref;
											
	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" ); # RE-CHECK
	}
	
	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
	}
	
	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 ( $new_loopcontrol_ref, $new_flowcontrol_ref );

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

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

	if ($propop eq "write_ctl")
	{
		print $_outfile_ "THAT\n";
		apply_loopcontrol_changes( \@new_loopcontrol, \@temploopcontrol);
		apply_flowcontrol_changes(\@new_flowcontrol, \@tempflowcontrol);
	}
	# return ( \@loopcontrol, \@flowcontrol, \@new_loopcontrol, \@new_flowcontrol );
	return ( \@loopcontrol, \@flowcontrol, \@new_loopcontrol, \@new_flowcontrol );
} # 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 ) = @_;
	say "Reading controls for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	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++;
	}
	return ( @flowcontrol );			
} # 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. THE NUMBER COUNT STARTS FROM 0.
	# $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, $countmorphing ) = @_;
	say "Reading controls constraints for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	@loopcontrol = @$swap;
	@flowcontrol = @$swap2;
	@temploopcontrol = @$swap3;
	@tempflowcontrol = @$swap4;

	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 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;
	}
	return( \@new_loopcontrol, \@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
";
			unless ($exeonfiles eq "n") 
			{
				print `$printthis`;
			}
			print TOFILE $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 ) = @_;
	say "Applying changes to flow controls for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.";

	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
";
			unless ($exeonfiles eq "n") # unless ($exeonfiles eq "n") 
			{ 
				print `$printthis`;
			}

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


####################################################### BEGINNING OF SECTION DEDICATED TO NET VARIATION
sub vary_net
{  	# IT IS CALLED FROM THE MAIN FILE
	my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $vary_net_ref, $countvar, $fileconfig, $mypath, $file, $countmorphing ) = @_;
	
	my @applytype = @$applytype_ref;
	my $zone_letter = $applytype[$countop][3];
	my @vary_net = @{ $vary_net_ref[ $countop ] };
	
	say "Executing variations 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"); # ZZZ THESE LETTERS HAVE TO BE CHECKED WITH REGARDS TO THE CHANGE OF PAGES!
	my @component_letters = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n", "o", "p", "q", "r", "s"); # ZZZ THESE LETTERS HAVE TO BE CHECKED WITH REGARDS TO THE CHANGE OF PAGES!
	# 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, $countmorphing ) = @_;
		
		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.
######################################################### END OF SECTION DEDICATED TO NET VARIATION

1;
