From 87bccfb3e5b47a8730fd3c5f77345332ceb331f4 Mon Sep 17 00:00:00 2001
From: Antonia Frank <antonia.frank@epfl.ch>
Date: Thu, 8 Aug 2024 17:36:27 +0200
Subject: [PATCH] Finalize the EC section with correct conversion factor &
 integration, reduce gdat_powers grid to times when waves are injected to the
 plasma

---
 matlab/TCV_IMAS/tcv_get_ids_core_sources.m | 203 ++++++++++++---------
 1 file changed, 114 insertions(+), 89 deletions(-)

diff --git a/matlab/TCV_IMAS/tcv_get_ids_core_sources.m b/matlab/TCV_IMAS/tcv_get_ids_core_sources.m
index 9f81305d..6a25f91d 100644
--- a/matlab/TCV_IMAS/tcv_get_ids_core_sources.m
+++ b/matlab/TCV_IMAS/tcv_get_ids_core_sources.m
@@ -52,7 +52,8 @@ powers_gdat = gdat(params_core_sources.shot,params_eff);
 % ohm
 ohm_t_grid = powers_gdat.ohm.t; ohm_n_t = numel(ohm_t_grid);
 
-id_ohm.description = 'Source from ohmic heating';
+main_desc = 'Source from ohmic heating'; production = 'IBS nodes';
+id_ohm.description = sprintf('%s from %s',main_desc,production);
 id_ohm.index = 7; id_ohm.name = 'ohmic';
 ids_core_sources.source{last_index+1} = source_template;
 ids_core_sources.source{last_index+1}.identifier = id_ohm;
@@ -106,7 +107,8 @@ if any(bs_t_grid-ohm_t_grid')>0
   warning('Bootstrap and ohmic time grids are not the same! Interpolation needed.')
 end
 
-id_bs.description = 'Bootstrap current';
+main_desc = 'Bootstrap current'; production = 'IBS nodes';
+id_bs.description = sprintf('%s from %s',main_desc,production);
 id_bs.index = 13; id_bs.name = 'bootstrap_current';
 ids_core_sources.source{last_index+1} = source_template;
 ids_core_sources.source{last_index+1}.identifier = id_bs;
@@ -136,86 +138,90 @@ ids_core_sources.source{last_index+1}.global_quantities.current_parallel = curre
 last_index = last_index+1;  % add if statement to only increment if bs source has been added
 
 %% ec
-ec_gdat = gdat(shot,'ec_data','ec_inputs',1);
+params_eff = params_eff_ref; 
+params_eff.data_request='ec_data';
+params_eff.ec_inputs = 1; % load EC input information
+ec_gdat = gdat(params_core_sources.shot,params_eff);
 
 if ~isempty(ec_gdat.ec.data) % if EC data available, fill sources
 
   ec_data = ec_gdat.ec.ec_data; ec_inputs = ec_gdat.ec.ec_inputs;
   % get tgrid from gdat ec_data
-  ec_data_tgrid = ec_data.p_dens.t; nt_ec_data = numel(ec_data_tgrid);
-
-  % get tgrid from gdat powers
-  ec_powers_tgrid = powers_gdat.ec.t; nt_ec_powers = numel(ec_powers_tgrid);
+  ec_tgrid = ec_data.p_dens.t; nt_ec_data = numel(ec_tgrid);
 
   % retrieve active launcher information from ec_inputs
   nb_launchers = numel(ec_inputs.launchers_active.data);
   active_launchers = find(ec_inputs.launchers_active.data==1)';
 
+  % find times of injected ec powers, for setting up source and
+  % interpolating the power & current densities on p_inj time grid
+  ec_powers_tgrid = powers_gdat.ec.t; %nt_ec_powers = numel(ec_powers_tgrid);
+  itime_ec = powers_gdat.ec.data(:,end)>0;
+  interp_tgrid = ec_powers_tgrid(itime_ec); nt_interp = numel(interp_tgrid);
+  interp_p_ec_injected = powers_gdat.ec.data(itime_ec,end);
+
   % Setup structures for active launchers from template
   main_desc = 'Source from electron cyclotron heating and current drive';
-  id_ec.index = 3; id_ec.name = 'ec';
+  production = 'TORAY';
+  id_ec.index = 3; id_ec.name = 'ec';  
   for i_lau = active_launchers
-    id_ec.description = sprintf('L%i/G%i, %s',i_lau,ec_inputs.gyro2launcher.data(i_lau),main_desc);
+    id_ec.description = sprintf('L%i/G%i, %s from %s double width CD profiles',i_lau,ec_inputs.gyro2launcher.data(i_lau),main_desc,production);
     ids_core_sources.source{last_index+i_lau} = source_template;
     ids_core_sources.source{last_index+i_lau}.identifier = id_ec;
-    ids_core_sources.source{last_index+i_lau}.profiles_1d(1:nt_ec_powers) = {profiles_template};
+    ids_core_sources.source{last_index+i_lau}.profiles_1d(1:nt_interp) = {profiles_template};
     ids_core_sources.source{last_index+i_lau}.global_quantities = globals_template;
   end
 
-  % get data for globals from gdat powers and fill in ids_structure
-  ec_total_pow = transpose(powers_gdat.ec.data(:,nb_launchers+1)); %use power from powers_gdat(injected ec power) instead of ec_data power
-  ec_total_pow(isnan(ec_total_pow)) = 0;
-  ec_total_cur = ec_data.cd_tot.data(nb_launchers+1,:);
-  ec_total_cur(isnan(ec_total_cur)) = 0;
-
-  for i_lau = active_launchers
-    ids_core_sources.source{last_index+i_lau}.global_quantities.time = ec_powers_tgrid;
-    ids_core_sources.source{last_index+i_lau}.global_quantities.power = ec_total_pow;
-    ids_core_sources.source{last_index+i_lau}.global_quantities.current_parallel = ec_total_cur;
-  end
-
   % load LIUQE data to convert
   % \tilde{j}_// = <jdotB>/(R0<Bphi/R>) to j_//0 = <jdotB>/B0; Bphi=T(psi)/R
-  [L,~,LY] = liuqe(shot,ec_data_tgrid,'iterq',50,'ilim',3,'icsint',true);
+  [L,~,LY] = liuqe(shot,ec_tgrid,'iterq',50,'ilim',3,'icsint',true);
   rho_pol_norm_liu = L.pQ; % normalized sqrt poloidal flux including axis
-  mu0    = 4*pi*10^-7;
-  Rm2_fs = LY.Q2Q;
-  Vprime = -1./LY.Q1Q; % Q1Q: -dpsi/dV
-  Ip_psi = LY.ItQ; % Ip(psi) = I_tor(psi)
-  T      = LY.TQ;
-  vol    = LY.VQ;
-  B2_fs  = mu0*Ip_psi.*2.*pi./Vprime + T.^2.*Rm2_fs;
-  toray_to_parallel = 1./(T.*Rm2_fs).*B2_fs./R0./B0;
+  mu0     = 4*pi*10^-7;
+  Rm2_fs  = LY.Q2Q;
+  mVprime = 1./LY.Q1Q; % Q1Q: -dpsi/dV
+  Ip_psi  = LY.ItQ; % Ip(psi) = I_tor(psi)
+  T       = LY.TQ;
+  vol     = LY.VQ;
+  B2_fs   = mu0*Ip_psi./mVprime + T.^2.*Rm2_fs;
+  R0 = ids_core_sources.vacuum_toroidal_field.r0;
+  B0 = interp1(ids_core_sources.time,ids_core_sources.vacuum_toroidal_field.b0,ec_tgrid);
+  jtoray_to_jpar0 = 2*pi./B0./(T.*Rm2_fs).*B2_fs;
 
   % interpolate on ec_data rho_pol grid
-  toray_to_parallel_ec = nan(size(toray_to_parallel));
-  vol_ec = nan(size(toray_to_parallel));
+  jtoray_to_jpar0_mapped = nan(size(ec_data.cd_dens.x));
+  vol_mapped = nan(size(ec_data.cd_dens.x));
   for ii = 1:nt_ec_data
-    toray_to_parallel_ec(:,ii) = ...
-      interp1(rho_pol_norm_liu,toray_to_parallel(:,ii),ec_data.cd_dens.grids.rho_pol_norm(:,ii));
-    vol_ec(:,ii) = ...
+    jtoray_to_jpar0_mapped(:,ii) = ...
+      interp1(rho_pol_norm_liu,jtoray_to_jpar0(:,ii),ec_data.cd_dens.grids.rho_pol_norm(:,ii));
+    vol_mapped(:,ii) = ...
       interp1(rho_pol_norm_liu,vol(:,ii),ec_data.cd_dens.grids.rho_pol_norm(:,ii));
   end
 
-  % interpoating p_dens profiles from 'ec_data_tgrid' grid (toray tgrid) to 'ec_powers_tgrid' (powers tgrid)
+  % interpoating p_dens profiles from 'ec_tgrid' grid (toray tgrid) to 'ec_powers_tgrid' (powers tgrid)
   p_dens        = ec_data.p_dens.data;
   p_integrated  = ec_data.p_integrated.data;
-  cd_dens       = nan(size(ec_data.cd_dens.data));
-  cd_integrated = nan(size(ec_data.cd_integrated.data));
-  %%
+  cd_dens       = ec_data.cd_dens_doublewidth.data; % use double width to have realistic deposition broadening
+  cd_integrated = ec_data.cd_integrated.data;
+  %
   for i_lau = active_launchers
-    cd_dens(:,i_lau,:) = squeeze(cd_dens(:,i_lau,:)).*toray_to_parallel_ec;
+    % convert to j// with conversion factor 
+    cd_dens(:,i_lau,:) = squeeze(cd_dens(:,i_lau,:)).*jtoray_to_jpar0_mapped;
     for ii = 1:nt_ec_data
-      cd_integrated(:,i_lau,ii) = cumtrapz(vol_ec(:,ii),cd_dens(:,i_lau,ii))/(2*pi*0.88);
+      % integrate j//
+      cd_integrated(:,i_lau,ii) = cumtrapz(vol_mapped(:,ii),cd_dens(:,i_lau,ii))/(2*pi*R0);
     end
   end
-%%
-  p_ec_injected = powers_gdat.ec.data;
-  ij = iround_os(ec_powers_tgrid,ec_data_tgrid);
-  sparse_p_ec_injected = p_ec_injected(ij,:); % injected ec power vals corresponding to ec_data_tgrid
+  
+%% remap ec outputs on power time grid 
+
+  ij = iround_os(interp_tgrid,ec_tgrid);
+  sparse_p_ec_injected = interp_p_ec_injected(ij,:); % injected ec power vals corresponding to ec_tgrid
   n_rho = size(p_dens, 1);
+  %rho grids to be interpolated on power time grid 
+  rho_pol_norm = ec_data.cd_dens.grids.rho_pol_norm;
+  rho_tor_norm = ec_data.cd_dens.grids.rho_tor_norm;
 
-  % calculate normalised profiles on ec_data_tgrid grid
+  % calculate normalised profiles on ec_tgrid grid
   norm_p_dens        = zeros(n_rho,nb_launchers+1,nt_ec_data);
   norm_p_integrated  = zeros(n_rho,nb_launchers+1,nt_ec_data);
   norm_cd_dens       = zeros(n_rho,nb_launchers+1,nt_ec_data);
@@ -228,10 +234,14 @@ if ~isempty(ec_gdat.ec.data) % if EC data available, fill sources
   end
 
   % interpolate normalised p_dens profiles on ec_powers_tgrid
-  interp_norm_p_dens        = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  interp_norm_p_integrated  = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  interp_norm_cd_dens       = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  interp_norm_cd_integrated = zeros(n_rho,nb_launchers+1,nt_ec_powers);
+  interp_norm_p_dens        = zeros(n_rho,nb_launchers+1,nt_interp);
+  interp_norm_p_integrated  = zeros(n_rho,nb_launchers+1,nt_interp);
+  interp_norm_cd_dens       = zeros(n_rho,nb_launchers+1,nt_interp);
+  interp_norm_cd_integrated = zeros(n_rho,nb_launchers+1,nt_interp);
+  % interpolate the rho_pol & rho_tor on ec_powers_tgrid
+  interp_rho_pol             = zeros(n_rho,nt_interp);
+  interp_rho_tor             = zeros(n_rho,nt_interp);
+  interp_rho_flag = 1;
   for i_lau = active_launchers
     for irho = 1:n_rho
       % get power and current density at each rho
@@ -240,47 +250,64 @@ if ~isempty(ec_gdat.ec.data) % if EC data available, fill sources
       trace_cd_dens       = squeeze(norm_cd_dens(irho,i_lau,:));
       trace_cd_integrated = squeeze(norm_cd_integrated(irho,i_lau,:));
       % interpolate on gdat powers tgrid
-      interp_norm_p_dens(irho,i_lau,:)        = interp1(ec_data_tgrid,trace_p_dens,ec_powers_tgrid);
-      interp_norm_p_integrated(irho,i_lau,:)  = interp1(ec_data_tgrid,trace_p_integrated,ec_powers_tgrid);
-      interp_norm_cd_dens(irho,i_lau,:)       = interp1(ec_data_tgrid,trace_cd_dens,ec_powers_tgrid);
-      interp_norm_cd_integrated(irho,i_lau,:) = interp1(ec_data_tgrid,trace_cd_integrated,ec_powers_tgrid);
+      interp_norm_p_dens(irho,i_lau,:)        = interpos(ec_tgrid,trace_p_dens,interp_tgrid);
+      interp_norm_p_integrated(irho,i_lau,:)  = interpos(ec_tgrid,trace_p_integrated,interp_tgrid);
+      interp_norm_cd_dens(irho,i_lau,:)       = interpos(ec_tgrid,trace_cd_dens,interp_tgrid);
+      interp_norm_cd_integrated(irho,i_lau,:) = interpos(ec_tgrid,trace_cd_integrated,interp_tgrid);
+      
+      % only interpolate rho grids once
+      if interp_rho_flag
+        interp_rho_pol(irho,:) = interpos(ec_tgrid,rho_pol_norm(irho,:),interp_tgrid');
+        interp_rho_tor(irho,:) = interpos(ec_tgrid,rho_tor_norm(irho,:),interp_tgrid');
+      end      
     end
+    interp_rho_flag = 0;
   end
 
-  % normalised & interpolated profiles * p_ec_injected on ec_powers_tgrid
-  interp_p_dens        = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  interp_p_integrated  = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  interp_cd_dens       = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  interp_cd_integrated = zeros(n_rho,nb_launchers+1,nt_ec_powers);
-  for it = 1:nt_ec_powers
-    interp_p_dens(:,:,it)        = interp_norm_p_dens(:,:,it).*p_ec_injected(it,:);
-    interp_p_integrated(:,:,it)  = interp_norm_p_integrated(:,:,it).*p_ec_injected(it,:);
-    interp_cd_dens(:,:,it)       = interp_norm_cd_dens(:,:,it).*p_ec_injected(it,:);
-    interp_cd_integrated(:,:,it) = interp_norm_cd_integrated(:,:,it).*p_ec_injected(it,:);
+  % normalised & interpolated profiles * p_ec_injected on interp_tgrid
+  interp_p_dens        = zeros(n_rho,nb_launchers+1,nt_interp);
+  interp_p_integrated  = zeros(n_rho,nb_launchers+1,nt_interp);
+  interp_cd_dens       = zeros(n_rho,nb_launchers+1,nt_interp);
+  interp_cd_integrated = zeros(n_rho,nb_launchers+1,nt_interp);
+  for it = 1:nt_interp
+    interp_p_dens(:,:,it)        = interp_norm_p_dens(:,:,it).*interp_p_ec_injected(it,:);
+    interp_p_integrated(:,:,it)  = interp_norm_p_integrated(:,:,it).*interp_p_ec_injected(it,:);
+    interp_cd_dens(:,:,it)       = interp_norm_cd_dens(:,:,it).*interp_p_ec_injected(it,:);
+    interp_cd_integrated(:,:,it) = interp_norm_cd_integrated(:,:,it).*interp_p_ec_injected(it,:);
   end
 
   % fill profiles_1d with interpolated profiles
   for i_lau = active_launchers
-    for ii = 1:nt_ec_powers
+    % initialize var for current_parallel and coupled power which needs to be obatined from
+    % integrated j// profiles and pdens last entry
+    current_parallel_tmp = nan(1,nt_interp);
+    power_coupled_tmp    = nan(1,nt_interp);
+    
+    for ii = 1:nt_interp
       % time
-      ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.time = ec_powers_tgrid(ii);
-      % rhotor grid
-      ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.grid.rho_tor_norm = ...
-        ec_data.p_dens.rhotor_norm(1,:); % constant in time
+      ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.time = interp_tgrid(ii);
+      % grids
+      ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.grid.rho_tor_norm = interp_rho_tor(:,ii);
+      ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.grid.rho_pol_norm = interp_rho_pol(:,ii);
       % power density
       ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.electrons.energy = ...
         interp_p_dens(:,i_lau,ii);
       % integrated power density
       ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.electrons.power_inside = ...
         interp_p_integrated(:,i_lau,ii);
-      % current density (to adapt to <J.B>/B0)
+      power_coupled_tmp(ii) = interp_p_integrated(end,i_lau,ii);
+      % current density
       ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.j_parallel = ...
         interp_cd_dens(:,i_lau,ii);
-      % integrated current density (to adapt to INTEGRAL(<J.B>/B0)*ds_phi)
+      % integrated current density
       ids_core_sources.source{last_index+i_lau}.profiles_1d{ii}.current_parallel_inside = ...
         interp_cd_integrated(:,i_lau,ii);
+      current_parallel_tmp(ii) = interp_cd_integrated(end,i_lau,ii);
     end
-  end
+    ids_core_sources.source{last_index+i_lau}.globa_quantities.time = interp_tgrid;
+    ids_core_sources.source{last_index+i_lau}.global_quantities.power = power_coupled_tmp;
+    ids_core_sources.source{last_index+i_lau}.global_quantities.current_parallel = current_parallel_tmp;
+  end 
 
   %add empty sources for rest of unsused launchers
   if numel(ids_core_sources.source)-last_index ~= nb_launchers
@@ -292,22 +319,20 @@ if ~isempty(ec_gdat.ec.data) % if EC data available, fill sources
 end
 
 %% nbi
-id_nbi.description = 'Source from Neutral Beam Injection';
-id_nbi.index = 2; id_nbi.name = 'nbi';
-%ids_core_sources.source{} = source_template;
-%ids_core_sources.source{}.identifier = id_nbi;
-%ids_core_sources.source{}.profiles_1d(1:n_t) = {profiles_template};
-%ids_core_sources.source{}.global_quantities(1:n_t) = {globals_template};
-
-
-% total
-id_total.description = 'Total source; combines all sources';
-id_total.index = 1; id_total.name = 'total';
-%ids_core_sources.source{} = source_template;
-%ids_core_sources.source{}.identifier = id_total;
-%ids_core_sources.source{}.profiles_1d(1:n_t) = {profiles_template};
-%ids_core_sources.source{}.global_quantities(1:n_t) = {globals_template};
-
+% id_nbi.description = 'Source from Neutral Beam Injection';
+% id_nbi.index = 2; id_nbi.name = 'nbi';
+% ids_core_sources.source{} = source_template;
+% ids_core_sources.source{}.identifier = id_nbi;
+% ids_core_sources.source{}.profiles_1d(1:n_t) = {profiles_template};
+% ids_core_sources.source{}.global_quantities(1:n_t) = {globals_template};
+
+%% total
+% id_total.description = 'Total source; combines all sources';
+% id_total.index = 1; id_total.name = 'total';
+% ids_core_sources.source{} = source_template;
+% ids_core_sources.source{}.identifier = id_total;
+% ids_core_sources.source{}.profiles_1d(1:n_t) = {profiles_template};
+% ids_core_sources.source{}.global_quantities(1:n_t) = {globals_template};
 
 %% add descriptions for profiles_1d
 
-- 
GitLab