From f5ee46a7e28b4592f9a7cda17e9ac49e68d3884c Mon Sep 17 00:00:00 2001
From: Eoin Clerkin <e.clerkin@gsi.de>
Date: Wed, 19 Apr 2023 12:56:15 +0200
Subject: [PATCH] Introduce total mass macro.

Allows the examintion of the mass of materials and component in the
simulation geometries.
---
 macro/geometry/README.md    |  14 +++
 macro/geometry/total_mass.C | 193 ++++++++++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+)
 create mode 100644 macro/geometry/total_mass.C

diff --git a/macro/geometry/README.md b/macro/geometry/README.md
index 4b639e4ed4..0be6d69dd4 100644
--- a/macro/geometry/README.md
+++ b/macro/geometry/README.md
@@ -203,6 +203,7 @@ Allows to run the `check_radlen` script on sets of geometries present in the sub
   Example for a version: `./macro/geometry/check_radlen_bulk.sh v22a` \
   Special tags which cannot be used in this way: `git`, `all`, `main`
 
+<<<<<<< HEAD
 
 ---
 
@@ -241,4 +242,17 @@ The lists of expected (known and ignored) overlaps are defined in 4 vectors at t
    ```
    root -l -b -q 'check_overlaps.C("<full filename with path>.geo.root", "<full filename with path for alignment matrices>.root")'
    ```
+=======
+---
+
+## total_mass.C
+
+Measures the total mass of the a geometry and setup, via a random dart method. Basic command may be run by, e.g., 
+
+```
+root -q total_mass.C'
+```
+
+This will output the total mass of each material in the setup.
+
 
diff --git a/macro/geometry/total_mass.C b/macro/geometry/total_mass.C
new file mode 100644
index 0000000000..a669bee088
--- /dev/null
+++ b/macro/geometry/total_mass.C
@@ -0,0 +1,193 @@
+/* Copyright (C) 2023 Facility for Antiproton and Ion Research in Europe, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Eoin Clerkin [committer] */
+
+#include <time.h>
+#include <stdlib.h>
+#include "TGeoManager.h"
+#include "TGeoNavigator.h"
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+
+TGeoManager* gman;
+TGeoNode* tmp_node;
+TGeoMedium* tmp_med;
+TGeoMaterial* tmp_mat;
+double tmp_den;
+
+#define NODE_MAX 70000
+#define SAMPLING 100000000
+
+typedef struct node_list {
+	char* NAME=(char *) calloc(200,sizeof(char)); // zero 200 characters
+	long int COUNT=0;
+	int MATERIAL_ID = 0;	// Given by the TGeoManager
+} node_list;
+
+// find nodal number or return next free.
+int find_node(char* strname, node_list* NODE_COUNT){
+	int j=0;
+
+	while(true){
+	//printf("%d COMPARE %s to %s is  %d\n", j, NODE_COUNT[j].NAME, strname, strcmp(NODE_COUNT[j].NAME,strname));
+	if(!*NODE_COUNT[j].NAME)goto not_allocated;
+	if(!strcmp(NODE_COUNT[j].NAME,strname)){
+		return j; // If not yet allocated.
+	};
+	j++;
+	if(j==NODE_MAX)fprintf(stderr,"WARNING: NODE_MAX EXCEEDED\n");
+	};
+not_allocated:
+return j;
+}
+void total_mass(
+int output=2
+){
+	// output as output controll variable
+	// output = 0 debuging
+	// output = 1 (default) list out the global materials
+	// output = 2 total list of individual nodes
+
+	int NUM=SAMPLING;
+
+	node_list NODE_COUNT[NODE_MAX];
+        strcpy(NODE_COUNT[0].NAME, "/cave_1");
+
+	char strname[200];
+	char NODE_PATH[200];
+
+	char ARRAY_PATH[20][40];
+
+	double TOTAL_MASS=0, SUM_DENSITY=0;
+
+	TFile file("test.geo.root","READ");
+	file.GetListOfKeys()->Print();
+	gman = (TGeoManager*) file.Get("FAIRGeom");
+	if (gman == nullptr) gman = gGeoManager;
+
+	TGeoNavigator *navig =  gman->AddNavigator();
+
+	int i=0,j=0,k=0;
+
+	int NUMBER_OF_MATERIALS=gman->GetListOfMaterials()->Last()->GetUniqueID();
+	long int MATERIAL_COUNT[100];
+
+	for(i=0;i<NUMBER_OF_MATERIALS;i++)MATERIAL_COUNT[i]=0; 
+
+	srand(time(NULL));
+	Double_t x, y, z;
+
+	// Full jpsi volume
+/*	double XMIN=-700, XMAX=700;
+	double YMIN=-570, YMAX=540;
+	double ZMIN=-100, ZMAX=1882;*/
+	//double ZMIN=-150, ZMAX=150;
+
+	// rich_v22a test
+	double XMIN=-265, XMAX=265;
+	double YMIN=-251, YMAX=251;
+	double ZMIN=110, ZMAX=335;
+
+	if(output==2)printf("RANDMAX IS %d\nResolution in X, Y, Z is %e %e %e\n", RAND_MAX, (XMAX-XMIN)/RAND_MAX, (YMAX-YMIN)/RAND_MAX, (ZMAX-ZMIN)/RAND_MAX);
+	double TOTAL_VOLUME = (XMAX-XMIN)*(YMAX-YMIN)*(ZMAX-ZMIN); // in cm3       for m3  times 10^-6 
+	if(output==2)printf("Total volume is %f m3 \n", (double) TOTAL_VOLUME/1000000 ); 
+
+	// I prevent rastoring bias when number of points is very large.
+	// My range will be modified by the random resolution to avoid fixing the single grid.
+	XMIN-=-1.0*( (rand()/RAND_MAX)*((XMAX-XMIN)/RAND_MAX) );
+	XMAX+=( (rand()/RAND_MAX)*((XMAX-XMIN)/RAND_MAX) );
+
+	YMIN-=-1.0*( (rand()/RAND_MAX)*((YMAX-YMIN)/RAND_MAX) );
+	YMAX+=( (rand()/RAND_MAX)*((YMAX-YMIN)/RAND_MAX) );
+
+	ZMIN-=-1.0*( (rand()/RAND_MAX)*((ZMAX-ZMIN)/RAND_MAX) );
+	ZMAX+=( (rand()/RAND_MAX)*((ZMAX-ZMIN)/RAND_MAX) );
+
+	// Position of STS  Tz=59.5
+	// double XMIN=-162, XMAX=162;
+	// double YMIN=-72, YMAX=72;
+	// double ZMIN=-102+59.5, ZMAX=20+59.5;
+
+	TOTAL_VOLUME = (XMAX-XMIN)*(YMAX-YMIN)*(ZMAX-ZMIN); // in cm3       for m3  times 10^-6 
+	if(output==2)printf("Modified total volume is %f m3 \n", (double) TOTAL_VOLUME/1000000 ); 
+	
+	for(i=1; i<=NUM; i++){
+
+        	x = (double) rand() / RAND_MAX * (XMAX-XMIN) + XMIN;
+        	y = (double) rand() / RAND_MAX * (YMAX-YMIN) + YMIN;
+        	z = (double) rand() / RAND_MAX * (ZMAX-ZMIN) + ZMIN;
+
+        	tmp_node = navig->FindNode(x,y,z);
+        	tmp_med = tmp_node->GetMedium();
+	        tmp_mat = tmp_med->GetMaterial();
+	        tmp_den = tmp_mat->GetDensity();
+
+		SUM_DENSITY += tmp_den;
+
+		MATERIAL_COUNT[gman->GetMaterialIndex(tmp_mat->GetName())]++;
+
+        j=0;
+        while(navig->GetMother(j)!=nullptr){
+                strcpy(ARRAY_PATH[j],(navig->GetMother(j)->GetName()));
+                j++;
+        };
+
+	strname[0]='\0';
+	while(j-->0){
+		strcat(strname,"/");
+		strcat(strname,ARRAY_PATH[j]);
+		ARRAY_PATH[j][0]='\0'; // zeroing
+	};
+
+//	printf("STRING WROTE: %s \n", strname);
+
+	j=find_node(strname, NODE_COUNT);
+	NODE_COUNT[j].COUNT++;
+	strcpy(NODE_COUNT[j].NAME,strname);
+
+	NODE_COUNT[j].MATERIAL_ID=gman->GetMaterialIndex(tmp_mat->GetName());
+
+	j=0;
+	};
+
+	// Ratio of materials 	         	    MATERIAL_COUNT/TOTAL_COUNT
+	// VOLUME OF MATERIAL 			    [ABOVE]*TOTAL_VOLUME
+	// TOTAL MASS OF MATERIAL		    [ABOVE]*DENSITY_OF_MATERIAL
+
+	long int TOTAL_COUNT=NUM;
+	double VC_RATIO  = (double) TOTAL_VOLUME/TOTAL_COUNT;
+
+		printf("TOTAL COUNT: %ld \n", TOTAL_COUNT);
+		printf("\n\n");
+		printf("\nCOUNT OF MATERIALS: ");
+		for(i=0;i<NUMBER_OF_MATERIALS;i++)printf("%f%% ", (double) 100*MATERIAL_COUNT[i]/TOTAL_COUNT );
+		printf("\n");
+		printf("\n\n");
+	        for(i=0;i<NUMBER_OF_MATERIALS;i++)printf("VOLUME OF %s IS %f \n", 
+		gman->GetMaterial(i)->GetName(),
+		(double) TOTAL_VOLUME*MATERIAL_COUNT[i]/TOTAL_COUNT);
+		printf("\n\n");
+		for(i=0;i<NUMBER_OF_MATERIALS;i++)if(output==2)printf("MASS OF %s IS %f kg\n", 
+		gman->GetMaterial(i)->GetName(), 
+		0.001*(gman->GetMaterial(i)->GetDensity())*TOTAL_VOLUME*MATERIAL_COUNT[i]/TOTAL_COUNT
+		);
+
+
+		printf("NODE \t COUNT \t VOLUME \t MATERIAL \t MASS \n");
+		printf("---------- \t ---------- \t ---------- \t ---------- \t ---------- \n");
+	
+		for(int k=0; k<5000; k++){
+			if(NODE_COUNT[k].COUNT==0)break;
+			printf(
+			"%s \t %ld \t %f \t %s \t %f \n", 
+			NODE_COUNT[k].NAME, 
+			NODE_COUNT[k].COUNT, 
+			(float) NODE_COUNT[k].COUNT*VC_RATIO, 
+			gman->GetMaterial(NODE_COUNT[k].MATERIAL_ID)->GetName(),
+			(float) NODE_COUNT[k].COUNT*VC_RATIO*(gman->GetMaterial(NODE_COUNT[k].MATERIAL_ID)->GetDensity())
+			);
+			}
+
+return;
+}
-- 
GitLab